PHP 8.0: Veri Türlerinde Yeni Gelişmeler (2/4)
PHP 8.0 sürümü henüz yayınlandı. Daha önceki hiçbir sürümde olmadığı kadar yeni özelliklerle dolu. Bunların tanıtımı dört ayrı makaleyi hak ediyor. İkinci bölümde, veri türlerine bir göz atacağız.
Geçmişe dönelim. Skaler tip ipuçlarının tanıtılması PHP 7'de önemli
bir atılımdı. Neredeyse gerçekleşmiyordu.
declare(strict_types=1)
sayesinde tamamen geriye dönük uyumlu ve
isteğe bağlı olan dahiyane çözümün yazarı Andreu Faulds topluluk tarafından sert bir
şekilde reddedildi. Neyse ki, Anthony
Ferrara o sırada onu ve öneriyi savundu, bir kampanya başlattı ve RFC
çok yakından geçti. Vay be. PHP 8'deki haberlerin çoğu efsanevi Nikita Popov sayesindedir ve hepsi
tereyağından kıl çeker gibi oylamadan geçmiştir. Dünya daha iyiye doğru
değişiyor.
PHP 8 türleri mükemmelliğe taşıyor. @param
,
@return
ve @var
gibi phpDoc ek açıklamalarının
büyük çoğunluğu yerel gösterimle değiştirilecektir. Ancak en önemlisi,
tipler PHP motoru tarafından kontrol edilecektir. Sadece string[]
gibi yapıların açıklamaları veya PHPStan için daha karmaşık ek
açıklamalar yorumlarda kalacaktır.
Sendika Türleri
Birlik türleri, bir değişkenin kabul edebileceği iki veya daha fazla türün bir numaralandırmasıdır:
class Button
{
private string|object $caption;
public function setCaption(string|object $caption)
{
$this->caption = $caption;
}
}
Bazı birlik türleri PHP'ye daha önce tanıtılmıştı. Örneğin nullable
tipler. Örneğin ?string
, string|null
birlik türüne
eşdeğerdir. Soru işareti gösterimi bir kısaltma olarak düşünülebilir.
Elbette, PHP 8'de de çalışır, ancak dikey çubuklarla birleştiremezsiniz.
Yani ?string|object
yerine string|object|null
yazmanız gerekir. Ayrıca, iterable
her zaman
array|Traversable
ile eşdeğerdir. float
'nin de bir
birlik türü olması sizi şaşırtabilir, çünkü her ikisini de kabul eder
int|float
, ancak değeri float
'a atar.
Birliklerde void
ve mixed
sözde tiplerini
kullanamazsınız çünkü bu bir anlam ifade etmez.
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)
{
...
}
Öte yandan, Nette DI'daki otomatik bağlantı, birleşik türleri reddeder. Şimdiye kadar, kurucunun bir ya da başka bir nesneyi kabul etmesinin mantıklı olacağı bir kullanım durumu yoktur. Elbette, böyle bir kullanım durumu ortaya çıkarsa, konteynerin davranışını buna göre ayarlamak mümkün olacaktır.
Nette\Utils\Reflection
adresindeki
getParameterType()
, getReturnType()
ve
getPropertyType()
yöntemleri, birlik türü durumunda bir istisna
oluşturur (bu, sürüm 3.1'de geçerlidir; önceki sürüm 3.0'da, bu
yöntemler null uyumluluğunu korumak için geri döner).
mixed
mixed
sözde tipi herhangi bir değeri kabul eder.
Parametreler ve özellikler söz konusu olduğunda, herhangi bir tür
belirtmediğimizde olduğu gibi aynı davranışla sonuçlanır. Peki, amacı
nedir? Bir türün ne zaman sadece eksik olduğunu ve ne zaman kasıtlı olarak
eksik olduğunu ayırt etmek mixed
.
İşlev ve yöntem geri dönüş değerleri söz konusu olduğunda, tür
belirtmemek mixed
kullanmaktan farklıdır. İşlevin bir şey
döndürmesini gerektirdiği için void
'un tam tersi anlamına
gelir. Eksik bir dönüş değeri ölümcül bir hata oluşturur.
Pratikte bunu nadiren kullanmanız gerekir, çünkü union tipleri sayesinde değeri tam olarak belirleyebilirsiniz. Bu nedenle yalnızca benzersiz durumlarda uygundur:
function dump(mixed $var): mixed
{
// print variable
return $var;
}
false
mixed
adresinden farklı olarak, yeni false
sözde
tipini yalnızca union tiplerinde kullanabilirsiniz. Bu, başarısızlık
durumunda tarihsel olarak false döndüren yerel fonksiyonların dönüş tipini
tanımlama ihtiyacından doğmuştur:
function strpos(string $haystack, string $needle): int|false
{
}
Bu nedenle, true
türü yoktur. Ne tek başına
false
, ne false|null
ne de bool|false
kullanabilirsiniz.
static
Pseudotype static
yalnızca bir yöntemin dönüş türü olarak
kullanılabilir. Yöntemin, nesnenin kendisiyle aynı türde bir nesne
döndürdüğünü söyler ( self
ise yöntemin tanımlandığı
sınıfı döndürdüğünü söyler). Akıcı arayüzleri 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 tür PHP 8'de yoktur ve gelecekte de tanıtılmayacaktır. Kaynaklar,
PHP'nin nesnelere sahip olmadığı zamanlardan kalma bir kalıntıdır. Yavaş
yavaş, kaynakların yerini nesneler alacaktır. Sonunda, tamamen ortadan
kalkacaklardır. Örneğin, PHP 8.0 resim kaynağını GdImage
nesnesi ile ve curl kaynağını CurlHandle
nesnesi ile
değiştirir.
Stringable
Sihirli bir yöntemle her nesne tarafından otomatik olarak uygulanan bir
arayüzdür __toString()
.
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 class Email implements Stringable
adresini
açıkça belirtmek mümkündür, ancak bu gerekli değildir.
Nette\Utils\Html
ayrıca eski IHtmlString
yerine
Nette\HtmlStringable
arayüzünü uygulayarak bu adlandırma
şemasını yansıtır. Örneğin bu türdeki nesneler Latte tarafından es
geçilmez.
Tip varyans, kontravaryans, kovaryans
Liskov İkame İlkesi (LSP), uzantı 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 belirtir. Yani, alt metot ebeveynden daha fazla argüman gerektirmemeli veya parametreler için daha dar bir tür aralığı kabul etmemelidir ve bunun tersi olarak, daha geniş bir tür aralığı döndürmemelidir. Ancak daha az sayıda döndürebilir. Neden mi? Çünkü aksi takdirde kalıtım bozulur. Bir fonksiyon belirli türde bir nesneyi kabul eder, ancak yöntemlerine hangi parametreleri aktarabileceği ve hangi türleri döndürecekleri hakkında hiçbir fikri olmaz. Herhangi bir çocuk bunu bozabilir.
Yani OOP'de alt sınıf şunları yapabilir:
- parametrelerde daha geniş bir tür aralığını kabul eder (buna contravariance denir)
- daha dar bir tür aralığı döndürür (kovaryans)
- ve özellikler tür değiştiremez (değişmezdirler)
PHP bunu 7.4 sürümünden beri yapabilmektedir ve PHP 8.0'da yeni tanıtılan tüm türler de contravariance ve covariance'ı desteklemektedir.
mixed
durumunda, çocuk dönüş değerini herhangi bir türe
daraltabilir, ancak bir değeri temsil etmediği, daha ziyade yokluğunu temsil
ettiği için void
olamaz. Çocuk ayrıca bir tür bildirimini de
atlayamaz, çünkü bu aynı zamanda bir değer yokluğuna da izin verir.
class A
{
public function foo(mixed $foo): mixed
{}
}
class B extends A
{
public function foo($foo): string
{}
}
Birlik türleri ayrıca 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
parametre olarak bool
'e ya da tam
tersi olarak bool
dönüş değeri olarak false
'e
genişletilebilir.
Kovaryans/karşıt varyansa karşı tüm suçlar PHP 8.0'da ölümcül bir hataya yol açar.
Bu serinin sonraki bölümlerinde, özniteliklerin ne olduğunu, PHP'de hangi yeni işlevlerin 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