Menu
Coddy logo textTech

Arayüz vs Soyut Sınıf

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 30 / 91.

Hem arayüzleri hem de soyut sınıfları öğrendiğinize göre, her birini ne zaman kullanacağımızı netleştirelim. Benzer görünseler de, farklı amaçlara hizmet ederler ve belirgin yeteneklere sahiptirler.

Özellik Interface (Arayüz) Abstract Class (Soyut Sınıf)
Metotlar Sadece metot imzaları Hem soyut hem de somut metotlar
Özellikler (Properties) Sadece sabitler Özelliklere sahip olabilir
Çoklu kalıtım Bir sınıf birden fazlasını uygulayabilir (implement) Bir sınıf sadece birini genişletebilir (extend)
Yapıcı Metot (Constructor) İzin verilmez Yapıcı metoda sahip olabilir

Birbiriyle ilişkisi olmayan sınıfların yerine getirebileceği bir sözleşme tanımlamak istediğinizde bir arayüz kullanın. Örneğin, ortak bir ataya sahip olmasalar bile hem bir Printer hem de bir Logger, bir Writable arayüzünü uygulayabilir.

Ortak kod paylaşan ilişkili sınıflarınız olduğunda bir soyut sınıf (abstract class) kullanın. Eğer Dog ve Cat sınıflarınızın her ikisi de aynı eat() metot uygulamasına ihtiyaç duyuyorsa, soyut bir Animal sınıfı bu kodu bir kez yazmanıza olanak tanır.

Her iki yaklaşımı da birleştirebilirsiniz. Bir sınıf, birden fazla arayüzü uygularken bir soyut sınıfı genişletebilir:

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

Önemli Nokta: Birbiriyle ilişkisi olmayan sınıflar genelinde yetenekleri tanımlamak için arayüzleri (interfaces) tercih edin. İlişkili sınıflar arasında kod paylaşmanız gerektiğinde soyut sınıfları (abstract classes) tercih edin.

challenge icon

Görev

Kolay

Soyut bir sınıfın ne zaman kullanılacağını, bir arayüzün (interface) ne zaman kullanılacağını ve her iki yaklaşımın nasıl etkili bir şekilde birleştirileceğini gösteren bir araç sistemi oluşturalım.

Araçların ortak özellikleri kalıtım yoluyla paylaştığı, ancak arayüzler aracılığıyla ek yetenekler kazanabildiği bir sistem oluşturacaksınız. Bu, gerçek dünyadaki tasarım kararlarını yansıtır: bir araba bir araçtır ("is a" - kalıtım), ancak aynı zamanda yakıt doldurulabilir olma ("has the capability" - arayüz) yeteneğine de sahiptir.

Kodunuzu dört dosya halinde düzenleyin:

  • Refuelable.php — Tek bir metot imzasına sahip bir Refuelable arayüzü tanımlayın: refuel($amount). Bu yetenek, kalıtım hiyerarşisinden bağımsız olarak yakıt ikmali gerektiren herhangi bir sınıfa uygulanabilir.
  • Vehicle.php — Tüm araçlar için paylaşılan işlevsellik sağlayan soyut bir Vehicle sınıfı tanımlayın. Korumalı (protected) bir $brand özelliğine ve korumalı bir $fuelLevel özelliğine (0'dan başlayan) sahip olmalıdır. Yapıcı metot (constructor) marka adını kabul eder. Markayı döndüren somut bir getBrand() metodu, mevcut yakıt seviyesini döndüren somut bir getFuelLevel() metodu ve alt sınıfların uygulaması gereken soyut bir drive() metodu ekleyin.
  • Car.phpVehicle sınıfını genişleten ve Refuelable arayüzünü uygulayan bir Car sınıfı oluşturun. Gerekli her iki dosyayı da en üste dahil edin. Yapıcı metot markayı kabul eder ve bunu üst sınıf yapıcısına iletir. drive() metodunu "[brand] car is driving" döndürecek şekilde uygulayın. refuel($amount) metodunu, miktarı yakıt seviyesine ekleyecek ve "[brand] refueled to [fuelLevel] liters" döndürecek şekilde uygulayın.
  • main.php — Car dosyasını dahil edin. İki girdi alacaksınız: bir marka adı ve bir yakıt miktarı (tam sayıya dönüştürün). Marka ile bir Car nesnesi oluşturun. İlk satıra drive() sonucunu yazdırın, ardından ikinci satıra yakıt miktarı ile refuel() sonucunu yazdırın.

Bu görev temel ayrımı göstermektedir: soyut Vehicle sınıfı kodu paylaşır ve bir "is-a" (bir ...-dır) ilişkisi kurar; Refuelable arayüzü ise araç olmalarını gerektirmeden diğer ilgisiz sınıflara (jeneratör veya tekne gibi) uygulanabilecek bir yetenek ekler.

Kopya kağıdı

Arayüzler ve soyut sınıflar farklı amaçlara hizmet eder:

Özellik Arayüz (Interface) Soyut Sınıf (Abstract Class)
Metotlar Yalnızca metot imzaları Hem soyut hem de somut metotlar
Özellikler (Properties) Yalnızca sabitler Özelliklere sahip olabilir
Çoklu kalıtım Bir sınıf birden fazlasını uygulayabilir Bir sınıf yalnızca birini genişletebilir
Yapıcı Metot (Constructor) İzin verilmez Yapıcı metoda sahip olabilir

İlişkisiz sınıflar için bir sözleşme tanımlamak üzere bir arayüz (interface) kullanın. İlgili sınıflar arasında ortak kod paylaşmak için bir soyut sınıf (abstract class) kullanın.

Bir sınıf, birden fazla arayüzü uygularken aynı zamanda bir soyut sınıfı genişletebilir:

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

Kendin dene

<?php
require_once 'Car.php';

// Girdiyi oku
$brand = trim(fgets(STDIN));
$fuelAmount = intval(trim(fgets(STDIN)));

// YAPILACAK: Marka ile bir Araba (Car) oluşturun

// YAPILACAK: İlk satıra drive() sonucunu yazdırın

// YAPILACAK: İkinci satıra yakıt miktarı ile refuel() 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