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