Nitelikler

PHP tekrar tekrar kullanılabilen bir yöntem kodu olarak trait ismini kullanarak nitelikleri tanımlamıştır.

Nitelikler, PHP gibi tek kalıtımlı dillerde kodun yeniden kullanımını sağlayan bir mekanizmadır. Yöntem kümelerini farklı sınıf hiyerarşilerinde yaşayan birçok bağımsız sınıfın içinde özgürce yeniden kullanımını mümkün kılarak tek kalıtımlı dillerdeki bazı sınırlamaları azaltmak için tasarlanmıştır. Sınıfların ve niteliklerin birleşiminden doğan anlamlılık, karmaşıklığı azaltan ve çoklu kalıtım ve iç içeliklerle ilgili bilinen sorunlardan kaçınan bir yol izlenerek tanımlanmıştır.

Nitelikler sınıflara benzemekle birlikte işlevselliği gruplamak için daha bir ince elenip sık dokunarak tasarlanmıştır. Bir niteliği kendi içinde örneklemek mümkün değildir. Geleneksel kalıtıma bir ekleme olup yatay davranış düzenini, yani kalıtım gerekmeksizin sınıf üyesi olmayı mümkün kılar.

Örnek 1 - Nitelik örneği

<?php
trait ezcReflectionReturnInfo {
function
getReturnType() { }
function
getReturnDescription() { }
}

class
ezcReflectionMethod extends ReflectionMethod {
use
ezcReflectionReturnInfo;

}

class
ezcReflectionFunction extends ReflectionFunction {
use
ezcReflectionReturnInfo;

}
?>

Öncelik sırası

Bir nitelikle gelen bir üye, bir temel sınıftan miras alınan bir üyenin yerine geçerse onu geçersiz kılar; sınıfın kendi üyeleri de niteliğin yerine geçerse onu geçersiz kılar.

Örnek 2 - Öncelik sırası örneği

Temel sınıftan miras alınan yöntem, DünyaDe niteliğinden MerhabaDünyam içine yerleştirilen üye tarafından geçersizleştirilmektedir. MerhabaDünyam sınıfı içinde tanımlı yöntemler için de davranış aynıdır. Öncelik sırası şöyledir: Temel sınıftan alınan yöntemleri geçersizleştiren nitelikleri geçerli sınıfın yöntemleri geçersizleştirir.

<?php
class Temel {
public function
merhabaDe() {
echo
'Merhaba ';
}
}

trait
DünyaDe {
public function
merhabaDe() {
parent::merhabaDe();
echo
'Dünya!';
}
}

class
MerhabaDünyam extends Temel {
use
DünyaDe;
}

$o = new MerhabaDünyam();
$o->merhabaDe();
?>

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

 Merhaba Dünya! 

Örnek 3 - Bir diğer öncelik sırası örneği

<?php
trait MerhabaDünya {
public function
merhabaDe() {
echo
'Merhaba Dünya!';
}
}

class
DünyaYetmez {
use
MerhabaDünya;
public function
merhabaDe() {
echo
'Merhaba Evren!';
}
}

$o = new DünyaYetmez();
$o->merhabaDe();
?>

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

 Merhaba Evren! 

Çoklu Nitelikler

Çok sayıda nitelik bir sınıfın içine use deyiminde virgüllerle ayrılarak yerleştirilebilir.

Örnek 4 - Çok sayıda niteliğin kullanımı

<?php
trait Merhaba {
public function
merhabaDe() {
echo
'Merhaba ';
}
}

trait
Dünya {
public function
dünyaDe() {
echo
'Dünya';
}
}

class
MerhabaDünyam {
use
Merhaba, Dünya;
public function
Bağır() {
echo
'!';
}
}

$o = new MerhabaDünyam();
$o->merhabaDe();
$o->dünyaDe();
$o->Bağır();
?>

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

 Merhaba Dünya! 

Çelişki Çözümleme

Bir yönteme aynı isme sahip iki nitelik yerleştirilirse çelişki açıkça çözümlenmediği takdirde ölümcül bir hataya sebep olur.

Aynı sınıfta kullanılan nitelikler arasındaki adlandırma çakışmasını çözümlemek için insteadof işleci birini seçmek amacıyla kullanılabilir.

Bu işlem yöntemi dışlamayı sağladığından as işleci yönteme takma ad eklemek için kullanılabilir. as işlecinin yöntemin ismini değiştirmediğini ve diğer yöntemleri etkilemediğini unutmayın.

Örnek 5 - Çelişki çözümleme örneği

Bu örnekte, Talker A ve B niteliklerini kullanıyor. A ve B çakışan yöntemlere sahip olduğundan B niteliğinden smallTalk ve A niteliğinden bigTalk kullanılmaktadır.

Aliased_Talker ise B'nin bigTalk gerçeklenimini talk diye bir takma ad altında kullanmak için as işlecinden yararlanmaktadır.

<?php
trait A {
public function
smallTalk() {
echo
'a';
}
public function
bigTalk() {
echo
'A';
}
}

trait
B {
public function
smallTalk() {
echo
'b';
}
public function
bigTalk() {
echo
'B';
}
}

class
Talker {
use
A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}

class
Aliased_Talker {
use
A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
?>

Yöntem Görünürlüğünü Değiştirme

Sergileyen sınıf içinde yöntemin görünürlüğünü ayarlamak için as sözdizimi kullanılabilir.

Örnek 6 - Yöntem görünürlüğünü değiştirme örneği

<?php
trait MerhabaDünya {
public function
merhabaDe() {
echo
'Merhaba Dünya!';
}
}

// merhabaDe görünürlüğünü değiştir
class Sınıfım1 {
use
MerhabaDünya { merhabaDe as protected; }
}

// Görünürlüğü ve ismi değişmiş yöntem
// merhabaDe görünürlüğü değişmedi
class Sınıfım2 {
use
MerhabaDünya { merhabaDe as private özelMerhabam; }
}
?>

Niteliklerden oluşturulmuş Nitelikler

Sınıflarda olduğu gibi nitelikler de bir diğerinin içinde kullanılabilir. Birden fazla nitelik kısmen veya tamamen bir diğer niteliğin içinde kullanılabilir.

Örnek 7 - Niteliklerden nitelik oluşturma örneği

<?php
trait Merhaba {
public function
merhabaDe() {
echo
'Merhaba ';
}
}

trait
Dünya {
public function
dünyaDe() {
echo
'Dünya!';
}
}

trait
MerhabaDünya {
use
Merhaba, Dünya;
}

class
MerhabaDünyam {
use
MerhabaDünya;
}

$o = new MerhabaDünyam();
$o->merhabaDe();
$o->dünyaDe();
?>

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

 Merhaba Dünya! 

Soyut Nitelik Yöntemleri

Nitelikler, kullanılacakları sınıfa yüklenmelerini sağlamak amacıyla soyut yöntemlerin kullanımını destekler. Public, protected ve private yöntemler desteklenir. PHP 8.0.0 öncesinde, sadece public ve protected soyut yöntemler destekleniyordu.

Dikkat

PHP 8.0.0 ve sonrasında, somut sınıfın imza uyumluluk kurallarına uygun olması gerekir. Evvelce imzası farklı olabiliyordu.

Örnek 8 - Gereksinimlerin soyut yöntemlerle ifadesi

<?php
trait Merhaba {
public function
merhabaDünyaDe() {
echo
'Merhaba'.$this->dünyaGetir();
}
abstract public function
dünyaGetir();
}

class
MerhabaDünyam {
private
$dünya;
use
Merhaba;
public function
dünyaGetir() {
return
$this->dünya;
}
public function
dünyaAta($val) {
$this->dünya = $val;
}
}
?>

Statik Nitelik Yöntemleri

Nitelikler statik değişkenleri, statik yöntemleri ve statik özellikleri tanımlayabilir.

Bilginize:

PHP 8.1.0 itibariyle, bir nitelik üzerinde doğrudan statik bir özelliğe erişim veya statik yöntem çağrısı önerilmemektedir. Statik yöntem ve özelliklere sadece niteliği kullanan sınıftan erişilmelidir.

Örnek 9 - Statik Değişkenler

<?php
trait Sayaç {
public function
arttır() {
static
$c = 0;
$c = $c + 1;
echo
"$c\n";
}
}

class
C1 {
use
Sayaç;
}

class
C2 {
use
Sayaç;
}

$o = new C1(); $o->arttır(); // 1 basar
$p = new C2(); $p->arttır(); // 1 basar
?>

Örnek 10 - Statik Yöntemler

<?php
trait StatikÖrnek {
public static function
bişeyYap() {
return
'Bir şey yapıyorum';
}
}

class
Örnek {
use
StatikÖrnek;
}

Örnek::bişeyYap();
?>

Örnek 11 - Statik Özellikler

<?php
trait StatikÖrnek {
public static
$statik = 'foo';
}

class
Örnek {
use
StatikÖrnek;
}

echo
Örnek::$statik;
?>

Özellikler

Nitelikler özellik tanımlayabilir.

Örnek 12 - Özellik tanımlama örneği

<?php
trait NitelikliÖzellik {
public
$x = 1;
}

class
ÖzellikÖrneği {
use
NitelikliÖzellik;
}

$örnek = new ÖzellikÖrneği;
örnek->x;
?>

Bir nitelik bir özellik tanımlarsa sınıf aynı isimde bir özelliği uyumlu (aynı görünürlük ve tür, salt okunur değiştirici ve ilk değer) olmadıkça tanımlayamaz, aksi takdirde ölümcül hata oluşur.

Örnek 13 - Çelişki yaratma örneği

<?php
trait ÖzellikliNitelik {
public
$aynı = true;
public
$farklı1 = false;
public
bool $farklı2;
public
bool $farklı3;
}

class
ÖzellikliÖrnek {
use
ÖzellikliNitelik;
public
$aynı = true;
public
$farklı1 = true; // ölümcül hata
public string $farklı2; // ölümcül hata
readonly protected bool $farklı3; // ölümcül hata
}
?>

Sabitler

PHP 8.2.0 itibariyle nitelikler sabitleri de tanımlayabilmektedir.

Örnek 14 - Sabitlerin Tanımlanması

<?php
trait SabitliNitelik {
public const
FLAG_MUTABLE = 1;
final public const
FLAG_IMMUTABLE = 5;
}

class
SabitliÖrnek {
use
SabitliNitelik;
}

$örnek = new SabitliÖrnek;
echo
$örnek::FLAG_MUTABLE; // 1
?>

Bir niteliğin tanımladığı sabiti bir sınıf uyumluluk kurallarına (aynı görünürlük, aynı ilk değer ve aynı sonuç) uymadan aynı isimle tekrar tanımlayamaz, aksi takdirde ölümcül hata oluşur.

Örnek 15 - Çelişki Çözümleme

<?php
trait SabitliNitelik {
public const
FLAG_MUTABLE = 1;
final public const
FLAG_IMMUTABLE = 5;
}

class
SabitliÖrnek {
use
SabitliNitelik;
public const
FLAG_IMMUTABLE = 5; // Ölümcül hata
}
?>
To Top