Trait'ler ve Kalıtım
Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 55 / 91.
Artık trait'lerin nasıl çalıştığını anladığınıza göre, kalıtıma (inheritance) karşı ne zaman trait kullanılacağını netleştirelim. Her ikisi de kodun yeniden kullanılmasını sağlar, ancak farklı amaçlara hizmet ederler ve belirgin özelliklere sahiptirler.
Kalıtım, bir "is-a" (bir ...-dır) ilişkisi kurar. Animal sınıfını genişleten bir Dog sınıfı, bir köpeğin bir hayvan olduğu anlamına gelir. Alt sınıf, üst sınıfın kimliğini miras alır ve üst sınıf türünün beklendiği her yerde kullanılabilir.
Trait'ler bir "has-a" (sahip olma) kabiliyeti sağlar. Bir sınıf Loggable trait'ini kullandığında, günlükleme işlevselliğine sahip olur - ancak bir logger'a dönüşmez. Trait'ler, sınıfın temelde ne olduğunu değiştirmeden davranış ekler.
<?php
// Kalıtım: Köpek bir Hayvandır
class Animal {
public function breathe(): void {
echo "Breathing";
}
}
class Dog extends Animal {
public function bark(): void {
echo "Woof!";
}
}
// Trait: Köpek günlükleme yeteneğine sahiptir
trait Loggable {
public function log(string $msg): void {
echo "Log: $msg";
}
}
class Cat extends Animal {
use Loggable;
}
Hatırlanması gereken temel farklar:
| Özellik | Kalıtım (Inheritance) | Trait'ler |
|---|---|---|
| İlişki | is-a | has-a yeteneği |
| Sınır | Yalnızca tek ebeveyn | Birden fazla trait'e izin verilir |
| Tür denetimi | instanceof ile çalışır | Tür kimliği yoktur |
| En uygun kullanım | Hiyerarşik ilişkiler | İlişkisiz sınıflar arasında paylaşılan davranışlar |
Sınıflar ortak bir kimliği paylaştığında kalıtımı kullanın. İlişkisiz sınıflar, aynı aile ağacının parçası olmadan aynı işlevselliğe ihtiyaç duyduğunda trait'leri kullanın.
Görev
KolayKalıtım (inheritance) ile trait'lerin ne zaman kullanılacağını gösteren bir araç sistemi inşa edelim. Kalıtım yoluyla ortak bir kimliği paylaşan araç hiyerarşisi oluşturacak ve trait'ler aracılığıyla çapraz kesen (cross-cutting) yetenekler ekleyeceksiniz.
Kodunuzu dört dosya halinde düzenleyeceksiniz:
Trackable.php— GPS izleme yeteneği sağlayanTrackableadında bir trait oluşturun. Trait şunlara sahip olmalıdır:- Özel (private) bir özellik:
$location(string) - Mevcut konumu saklayan bir metot:
setLocation(string $location) "Location: "ile konumu birleştirip döndüren bir metot:getLocation()
- Özel (private) bir özellik:
Vehicle.php— "is-a" (bir ...-dır) ilişkisini kuran temel birVehiclesınıfı oluşturun. Trait dosyasını dahil edin. Korumalı (protected) bir$brandözelliği tanımlamak için constructor promotion kullanın."Vehicle: "ile markayı birleştirip döndüren birdescribe()metodu ekleyin. Filomuzdaki tüm araçlar GPS'e sahip olacağı için bu sınıfTrackabletrait'ini kullanmalıdır.Car.php—Vehiclesınıfını genişleten birCarsınıfı oluşturun. Vehicle dosyasını dahil edin. Markayı ve özel (private) bir$doors(integer) özelliğini kabul etmek için constructor promotion kullanın. Üst sınıfın (parent) constructor'ını marka ile çağırın.describe()metodunu,"Car: [brand] with [doors] doors"döndürecek şekilde geçersiz kılın (override).main.php— Car dosyasını dahil edin. Üç girdi alacaksınız: bir marka adı, kapı sayısı ve bir konum dizesi. BirCarörneği oluşturun, konumunu ayarlayın ve ardından iki satır yazdırın:describe()metodunu çağırmanın sonucugetLocation()metodunu çağırmanın sonucu
Burada kalıtım ve trait'lerin nasıl birlikte çalıştığına dikkat edin: Car bir Vehicle'dır (kalıtım kimliği belirler), Vehicle ise izleme yeteneğine sahiptir (trait davranış ekler). Bir şeyin araç olup olmadığını kontrol etmek için instanceof Vehicle kullanabilirsiniz, ancak kontrol edilecek bir "Trackable" türü yoktur; bu iki yaklaşım arasındaki temel fark budur.
Kopya kağıdı
"is-a" (bir ...-dır) ilişkileri için kalıtımı (inheritance) ve "has-a" (bir ...-ya sahiptir) yetenekleri için trait'leri kullanın.
Kalıtım kimlik oluşturur - bir alt sınıf, üst sınıfın bir türüdür (is a) ve üst sınıfın beklendiği her yerde kullanılabilir.
Trait'ler, sınıf kimliğini değiştirmeden davranış ekler - bir sınıf belirli bir işlevselliğe sahiptir (has) ancak o şeyin kendisine dönüşmez.
<?php
// Inheritance: Dog IS an Animal (Köpek bir Hayvandır)
class Animal {
public function breathe(): void {
echo "Breathing";
}
}
class Dog extends Animal {
public function bark(): void {
echo "Woof!";
}
}
// Trait: Cat HAS logging capability (Kedinin günlükleme yeteneği vardır)
trait Loggable {
public function log(string $msg): void {
echo "Log: $msg";
}
}
class Cat extends Animal {
use Loggable;
}
| Özellik | Kalıtım (Inheritance) | Trait'ler |
|---|---|---|
| İlişki | is-a (bir ...-dır) | has-a (bir yeteneğe sahiptir) |
| Sınır | Yalnızca tek ebeveyn | Birden fazla trait kullanılabilir |
| Tür denetimi | instanceof ile çalışır | Tür kimliği yoktur |
| En iyi kullanım | Hiyerarşik ilişkiler | İlişkisiz sınıflar arasında paylaşılan davranışlar |
Sınıfların ortak bir kimliği paylaştığı hiyerarşik ilişkiler için kalıtımı kullanın. Birbiriyle ilişkisiz sınıflar arasındaki paylaşılan davranışlar için trait'leri kullanın.
Kendin dene
<?php
// Ana dosya - Car örneğini oluşturun ve test edin
// YAPILACAK: Car.php dosyasını dahil edin
// Girdileri oku
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));
// YAPILACAK: Marka ve kapı sayısı ile bir Car örneği oluşturun
// YAPILACAK: Arabanın konumunu ayarlayın
// YAPILACAK: describe() sonucunu yazdırın
// YAPILACAK: getLocation() sonucunu yazdırın
?>Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesneler$this Anahtar KelimesiMetotlarÖzelliklerYapıcı Metot (__construct)Yıkıcı Metot (__destruct)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımparent:: Anahtar KelimesiMetot Geçersiz Kılmafinal Anahtar KelimesiSoyut SınıflarÖzet - Çalışan Hiyerarşisi7Kapsülleme
Public, Protected, PrivateErişim Belirleyicilere Derinlemesine BakışGetter ve Setter MetotlarıBilgi GizlemeConstructor Promotion (8.0)Özet - Öğrenci Kayıt Sistemi10İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımDependency InjectionAnonim SınıflarEnum'lar (PHP 8.1)Fiber'lar (PHP 8.1)Nesne Klonlama: Derinlemesine İncelemeGenerator'lar ve Iterator'lar13Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıRepository Kalıbı2İsim Alanları ve Autoloading
İsim Alanlarına Girişuse Anahtar KelimesiPSR-4 Autoloading StandartıComposer AutoloaderÖzet - Düzenli Proje5Arayüzler ve Sözleşmeler
Arayüzlere GirişArayüzleri UygulamaBirden Fazla Arayüz UygulamaArayüz vs Soyut SınıfArayüzler ile Tip BelirlemeÖzet - Şekil Hesaplayıcı8Sihirli Metotlar
Sihirli Metotlara Giriş__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Nesne Klonlama__serialize & __unserializeÖzet - Özel Koleksiyon3Sınıf Özellikleri
Örnek ve Statik ÖzelliklerSınıflarda SabitlerStatik Metotlar ve ÖzelliklerPrivate ve Protected ÖzelliklerReadonly Özellikler (PHP 8.1)Özet - Banka Hesabı Yöneticisi6Çok Biçimlilik
Metot Geçersiz Kılmaya Yeniden BakışArayüzler ile Çok BiçimlilikType Hinting ve Union TypesLate Static BindingÖzet - Ödeme İşlemcisi9Trait'ler
Trait'lere GirişÇoklu Trait KullanımıTrait Çakışma ÇözümüTrait'lerde Soyut MetotlarTrait'ler ve Kalıtım12Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı15Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi