Menu
Coddy logo textTech

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:

ÖzellikKalıtım (Inheritance)Trait'ler
İlişkiis-ahas-a yeteneği
SınırYalnızca tek ebeveynBirden fazla trait'e izin verilir
Tür denetimiinstanceof ile çalışırTür kimliği yoktur
En uygun kullanımHiyerarş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.

challenge icon

Görev

Kolay

Kalı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ğlayan Trackable adı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()
    Bu trait bir "has-a" (sahip olma) yeteneğini temsil eder; herhangi bir araç izleme özelliğine sahip olabilir, ancak izleme özelliğine sahip olmak bir şeyi araç yapmaz.
  • Vehicle.php — "is-a" (bir ...-dır) ilişkisini kuran temel bir Vehicle sı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 bir describe() metodu ekleyin. Filomuzdaki tüm araçlar GPS'e sahip olacağı için bu sınıf Trackable trait'ini kullanmalıdır.
  • Car.phpVehicle sınıfını genişleten bir Car sı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. Bir Car örneği oluşturun, konumunu ayarlayın ve ardından iki satır yazdırın:
    • describe() metodunu çağırmanın sonucu
    • getLocation() 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;
}
ÖzellikKalıtım (Inheritance)Trait'ler
İlişkiis-a (bir ...-dır)has-a (bir yeteneğe sahiptir)
SınırYalnızca tek ebeveynBirden fazla trait kullanılabilir
Tür denetimiinstanceof ile çalışırTür kimliği yoktur
En iyi kullanımHiyerarş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
?>
quiz iconKendini test et

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