PHP 8.0: Veri Tipleri (2/4)
PHP 8.0 sürümü yayınlandı. Daha önceki hiçbir sürümde olmadığı kadar yeniliklerle dolu. Tanıtımları tam dört ayrı makale gerektirdi. Bu ikincisinde veri tiplerine bakacağız.
			Tarihe geri dönelim. PHP 7'nin temel atılımı, skaler tip ipuçlarının
getirilmesiydi. Neredeyse gerçekleşmiyordu.
declare(strict_types=1) sayesinde tamamen geriye dönük uyumlu ve
isteğe bağlı olan harika çözümün yazarı Andrea Faulds, topluluk tarafından çirkin bir
şekilde reddedildi. Neyse ki, o zamanlar Anthony Ferrara hem onu hem de önerisini
savundu, bir kampanya başlattı ve RFC çok az bir farkla geçti. Ufff. PHP
8'deki yeniliklerin çoğu efsanevi Nikita
Popov tarafından yapıldı ve oylamada tereyağından kıl çeker gibi
geçti. Dünya daha iyiye doğru değişiyor.
PHP 8, tipleri mükemmelliğe taşıyor. Koddaki @param,
@return ve @var phpDoc ek açıklamalarının büyük
çoğunluğu ortadan kalkacak ve yerini yerel yazım ve en önemlisi PHP motoru
tarafından kontrol alacak. Yorumlarda yalnızca string[] gibi
yapıların açıklamaları veya PHPStan için daha karmaşık ek açıklamalar
kalacak.
Union Tipleri
Union tipleri, bir değerin alabileceği iki veya daha fazla tipin bir listesidir:
class Button
{
	private string|object $caption;
	public function setCaption(string|object $caption)
	{
		$this->caption = $caption;
	}
}
PHP zaten bazı özel union tiplerini biliyordu. Örneğin,
?string gibi nullable tipler, bu string|null union
tipinin eşdeğeridir ve soru işareti yazımı sadece bir kısaltma olarak
kabul edilebilir. Elbette PHP 8'de de çalışır, ancak dikey çizgilerle
birleştirilemez, yani ?string|object yerine tam
string|object|null yazmak gerekir. Ayrıca, iterable
her zaman array|Traversable eşdeğeriydi. Belki de
float'ın aslında int|float kabul eden, ancak
float'a dönüştüren bir union tipi olması sizi
şaşırtabilir.
Union'larda void ve mixed sahte tipleri
kullanılamaz, çünkü bunun hiçbir anlamı olmazdı.
Nette birlik türleri için hazır. Schema'da, Expect::from()
bunları kabul eder ve sunum yapanlar da bunları kabul eder. Bunları örneğin
render ve action yöntemlerinde kullanabilirsiniz:
public function renderDetail(int|array $id)
{
	...
}
Tersine, Nette DI'daki otomatik kablolama (autowiring) union tiplerini reddeder. Henüz, örneğin bir yapıcının ya o ya da bu nesneyi kabul etmesinin anlamlı olacağı bir kullanım durumu yoktur. Elbette ortaya çıkarsa, konteynerin davranışını buna göre ayarlamak mümkün olacaktır.
Nette\Utils\Reflection'daki getParameterType(),
getReturnType() ve getPropertyType() metotları, union
tipi durumunda bir istisna fırlatır (sürüm 3.1'de, eski 3.0 sürümünde
uyumluluk nedeniyle null döndürürler).
mixed
mixed sahte tipi, değerin kesinlikle herhangi bir şey
olabileceğini söyler.
Parametreler ve özellikler durumunda, bu aslında hiçbir tip
belirtmediğimiz zamankiyle aynı davranıştır. Öyleyse ne işe yarar? Tipin
basitçe eksik olduğu ile gerçekten mixed olduğu arasında
ayrım yapabilmek için.
Fonksiyon ve metotların dönüş değeri durumunda, tip belirtmemek ile
mixed tipini belirtmek farklıdır. Aslında void'un
tersidir, çünkü fonksiyonun bir şey döndürmesi gerektiğini söyler. Eksik
return o zaman ölümcül bir hatadır.
Pratikte, onu nadiren kullanmalısınız, çünkü union tipleri sayesinde değeri daha kesin olarak belirleyebilirsiniz. Bu nedenle istisnai durumlarda kullanışlıdır:
function dump(mixed $var): mixed
{
	// değişkeni yazdır
	return $var;
}
false
Yeni false sahte tipi ise yalnızca union tiplerinde
kullanılabilir. Başarısızlık durumunda tarihsel olarak false döndüren
yerel fonksiyonların dönüş değerinin tipini yerel olarak tanımlama
ihtiyacından doğmuştur:
function strpos(string $haystack, string $needle): int|false
{
}
Bu nedenle, true tipi yoktur, tek başına false
veya false|null ya da bool|false kullanılamaz.
static
static sahte tipi yalnızca bir metodun dönüş tipi olarak
kullanılabilir. Metodun, nesnenin kendisiyle aynı türden bir nesne
döndürdüğünü söyler (oysa self, metodun tanımlandığı
sınıfı döndürdüğünü söyler). Bu, akıcı arayüzleri (fluent
interfaces) tanımlamak için mükemmeldir:
class Item
{
	public function setValue($val): static
	{
		$this->value = $val;
		return $this;
	}
}
class ItemChild extends Item
{
	public function childMethod()
	{
	}
}
$child = new ItemChild;
$child->setValue(10)
	->childMethod();
resource
Bu tip PHP 8'de mevcut değildir ve gelecekte de getirilmeyecektir. Kaynaklar
(Resources), PHP'nin henüz nesnelere sahip olmadığı zamanlardan kalma
tarihsel bir kalıntıdır. Kaynaklar yavaş yavaş nesnelerle değiştirilecek
ve zamanla bu tip tamamen ortadan kalkacaktır. Örneğin, PHP 8.0, resmi temsil
eden kaynağı GdImage nesnesiyle ve curl bağlantı
kaynağını CurlHandle nesnesiyle değiştirir.
Stringable
Bu, sihirli __toString() metoduna sahip her nesnenin otomatik
olarak uyguladığı bir arayüzdür.
class Email
{
	public function __toString(): string
	{
		return $this->value;
	}
}
function print(Stringable|string $s)
{
}
print('abc');
print(new Email);
Sınıf tanımında açıkça class Email implements Stringable
belirtmek mümkündür, ancak gerekli değildir.
Bu adlandırma stili, önceki IHtmlString yerine
Nette\HtmlStringable arayüzünü uygulayan
Nette\Utils\Html tarafından da yansıtılır. Bu tür nesneler
daha sonra örneğin Latte tarafından kaçış işlemine tabi tutulmaz.
Tip varyansı, kontravaryans, kovaryans
Liskov Yerine Geçme Prensibi (Liskov Substitution Principle – LSP), bir sınıfın alt sınıflarının ve arayüz uygulamalarının asla ebeveynden daha fazlasını gerektirmemesi ve daha azını sağlamaması gerektiğini söyler. Yani, bir alt sınıfın metodu, ebeveynden daha fazla argüman gerektiremez veya parametrelerde daha dar bir tip aralığını kabul edemez ve tersine daha geniş bir tip aralığı döndüremez. Ancak daha dar bir aralık döndürebilir. Neden? Çünkü aksi takdirde kalıtım hiç çalışmazdı. Fonksiyon belirli bir türden bir nesneyi kabul etse bile, metotlara hangi parametrelerin iletilebileceğini ve gerçekte ne döndüreceklerini bilemezdi, çünkü herhangi bir alt sınıf bunu bozabilirdi.
Dolayısıyla OOP'de şu geçerlidir: alt sınıf şunları yapabilir:
- parametrelerde daha geniş bir tip aralığını kabul edebilir (buna kontravaryans denir)
 - daha dar bir tip aralığı döndürebilir (kovaryans)
 - ve özellikler tipi değiştiremez (değişmezdirler)
 
PHP bunu 7.4 sürümünden beri yapabiliyor ve PHP 8.0'da tanıtılan tüm yeni tipler de kontravaryans ve kovaryansı destekliyor.
mixed durumunda, alt sınıf dönüş değerini herhangi bir
tipe daraltabilir, ancak void'a daraltamaz, çünkü bu bir değer
tipi değil, onun yokluğudur. Alt sınıf da tip belirtmeyemez, çünkü bu da
yokluğa izin verir.
class A
{
    public function foo(mixed $foo): mixed
    {}
}
class B extends A
{
    public function foo($foo): string
    {}
}
Ayrıca union tipleri parametrelerde genişletilebilir ve dönüş değerlerinde daraltılabilir:
class A
{
    public function foo(string|int $foo): string|int
    {}
}
class B extends A
{
    public function foo(string|int|float $foo): string
    {}
}
Ayrıca, false parametrede bool'a genişletilebilir
veya tersine bool dönüş değerinde false'a
daraltılabilir.
Kovaryans/kontravaryansa karşı tüm ihlaller PHP 8.0'da ölümcül hataya yol açar.
Gelecek bölümlerde niteliklerin ne olduğunu, PHP'de hangi yeni fonksiyonların ve sınıfların ortaya çıktığını göstereceğiz ve Just in Time Compiler'ı tanıtacağız.
	
			
			
			
Yorum göndermek için lütfen giriş yapın