Çok Özgüllük ve Az Özgüllük

PHP 7.2.0'da, bir çocuk yöntem değiştirgelerindeki tür sınırlamaları kaldırılarak az özgüllüklere kısmen girildi. PHP 7.4.0'dan itibaren, az ve çok özgüllüklere tam destek eklendi.

Çok özgüllük, bir çocuk yöntemin ebeveyn yönteminden daha özellikli bir tür döndürmesine izin verir. Buna karşın, az özgüllük, bir değiştirgenin bir çocuk yöntemin içinde ebeveyndekinden daha az özellikli olmasına izin verir.

Aşağıdaki durumda tür belirtiminin daha belirgin olduğu varsayılır:

  • Bir union tür için tür adı belirtmemek
  • Bir sınıf türü yerine çocuk sınıf türü belirtmek
  • float yerine int belirtmek
Tersi doğruysa, o tür sınıfının daha az belirgin olduğu varsayılır.

Çok Özgüllük

Çok özgüllüğün nasıl çalıştığını göstermek için, basit bir soyut ebeveyn sınıf olarak Hayvan sınıfı oluşturulup Kedi ve Köpek çocuk sınıflarına genişletildi.

<?php

abstract class Hayvan
{
    protected 
string $isim;

    public function 
__construct(string $isim)
    {
        
$this->name $isim;
    }

    abstract public function 
konuş();
}

class 
Köpek extends Hayvan
{
    public function 
konuş()
    {
        echo 
$this->name " havlar";
    }
}

class 
Kedi extends Hayvan
{
    public function 
konuş()
    {
        echo 
$this->name " miyavlar";
    }
}

Bu örnekte yöntemlerin hiçbiri değer döndürmemektedir. Hayvan, Kedi ve Köpek sınıfı türünde yeni bir nesne döndüren birkaç arayüz eklenecektir.

<?php

interface HayvanYuvası
{
    public function 
sahiplen(string $isim): Hayvan;
}

class 
KediYuvası implements HayvanYuvası
{
    public function 
sahiplen(string $isim): Kedi // Hayvan türünde bir sınıf yerine Kedi türünde bir sınıf döner
    
{
        return new 
Kedi($isim);
    }
}

class 
KöpekYuvası implements HayvanYuvası
{
    public function 
sahiplen(string $isim): Köpek // Hayvan türünde bir sınıf yerine Köpek türünde bir sınıf döner
    
{
        return new 
Köpek($isim);
    }
}

$mırnav = (new KediYuvası)->sahiplen("Tekir");
$mırnav->konuş();
echo 
"\n";

$kuçu = (new KöpekYuvası)->sahiplen("Çomar");
$kuçu->konuş();

Yukarıdaki örneğin çıktısı:

Tekir miyavlar
Çomar havlar

Az Özgüllük

Hayvan, Kedi ve Köpek sınıflarıyla önceki örneğe devam ederek, bunlara Yem ve HayvanYemi sınıflarını dahil edip Hayvan soyut sınıfına ye(HayvanYemi $yem) yöntemini ekleyelim.

<?php

class Yem {}

class 
HayvanYemi extends Yem {}

abstract class 
Hayvan
{
    protected 
string $isim;

    public function 
__construct(string $isim)
    {
        
$this->name $isim;
    }

    public function 
ye(HayvanYemi $yem)
    {
        echo 
$this->name " " get_class($yem) . "yer";
    }
}

Az özgüllüğün davranışını görmek için, herhangi bir Yem türü nesneye izin vermek için Köpek sınıfında ye yöntemi geçersiz kılınır. Kedi sınıfı değişmeden kalır.

<?php

class Köpek extends Hayvan
{
    public function 
ye(Yem $yem) {
        echo 
$this->name " " get_class($yem) . "yer";
    }
}

Aşağıdaki örnek az özgüllüğün davranışını gösterir:

<?php

$mırnav 
= (new KediYuvası)->sahiplen("Tekir");
$kediYemi = new HayvanYemi();
$mırnav->ye($kediYemi);
echo 
"\n";

$kuçu = (new KöpekYuvası)->sahiplen("Çomar");
$kemik = new Yem();
$kuçu->ye($kemik);

Yukarıdaki örneğin çıktısı:

Tekir HayvanYemi yer
Çomar Yem yer

Peki $mırnav $kemik yemeye çalışırsa ne olur?

$mırnav->ye($kemik);

Yukarıdaki örneğin çıktısı:

Fatal error: Uncaught TypeError: Argument 1 passed to Hayvan::ye() must be an instance of HayvanYemi, instance of Yem given
Türkçesi: Ölümcül hata: ... : Hayvan::ye() yöntemine aktarılan 1. değiştirge
bir HayvanYemi örneği olmalı, Yem örneği verildi