Menu
Coddy logo textTech

Arayüzler Yoluyla Çok Biçimlilik

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

Önceki derste, alt sınıfların üst sınıf metotlarını geçersiz kıldığı kalıtım yoluyla çok biçimliliği gördün. Arayüzler, özellikle ortak davranışları paylaşan ve birbiriyle ilişkili olmayan sınıflarla çalışırken, çok biçimliliğe ulaşmak için başka bir güçlü yol sunar.

Arayüzlerle birlikte polimorfizm sözleşmenin kendisinden gelir. Bir arayüzü uygulayan herhangi bir sınıf, kalıtım hiyerarşisinden bağımsız olarak belirli methodlara sahip olduğunu garanti eder:

<?php
interface Notifiable {
    public function send(string $message);
}

class EmailNotifier implements Notifiable {
    public function send(string $message) {
        return "Email: " . $message;
    }
}

class SMSNotifier implements Notifiable {
    public function send(string $message) {
        return "SMS: " . $message;
    }
}

class PushNotifier implements Notifiable {
    public function send(string $message) {
        return "Push: " . $message;
    }
}

function notify(Notifiable $notifier, string $message) {
    return $notifier->send($message);
}

echo notify(new EmailNotifier(), "Hello") . "\n";
echo notify(new SMSNotifier(), "Hello") . "\n";
echo notify(new PushNotifier(), "Hello");

Çıktı:

Email: Hello
SMS: Hello
Push: Hello

notify() işlevi, herhangi bir Notifiable nesnesiyle çalışır. Bu sınıflar ortak bir üst sınıfı paylaşmaz; aynı arayüzü uygulamaları dışında birbirleriyle tamamen ilgisizdirler. Kalıtım tabanlı çok biçimliliğe kıyasla temel avantaj şudur: ilgisiz sınıfları soylarına göre değil, yeteneklerine göre gruplayabilirsiniz.

Temel Nokta: Arayüz tabanlı çok biçimlilik, ortak davranışa dayalı olarak birbiriyle ilişkili olmayan sınıfların birbirinin yerine kullanılmasını sağlar; bu da kodunuzu daha esnek ve belirli uygulamalardan daha bağımsız hâle getirir.

challenge icon

Görev

Kolay

Arayüz tabanlı çok biçimliliği gösteren bir depolama sistemi oluşturalım. Birbirleriyle hiçbir ortak noktası olmayan, ancak her ikisi de aynı depolama arayüzünü uygulayan farklı depolama arka uçları, bir dosya sistemi ve bir veritabanı oluşturacaksın. Tek bir işlev herhangi bir depolama türüyle çalışacak ve arayüzlerin tamamen ilgisiz sınıflar arasında çok biçimliliği nasıl mümkün kıldığını gösterecek.

Kodunu dört dosyaya ayıracaksın:

  • Storable.php: İki yöntem imzasına sahip bir Storable arayüzü tanımla: save($key, $data) ve retrieve($key). Bu sözleşme, herhangi bir depolama sisteminin dahili olarak nasıl uygulandığından bağımsız olarak veri depolayabilmesini ve alabilmesini sağlar.
  • FileStorage.php: Storable uygulayan bir FileStorage sınıfı oluştur. Arayüz dosyasını dahil et. Sınıfın, oluşturucu aracılığıyla ayarlanan private bir $directory özelliği olmalı. save($key, $data) yöntemini "Saving '[data]' to file [directory]/[key].txt" döndürecek şekilde uygula. retrieve($key) yöntemini "Reading from file [directory]/[key].txt" döndürecek şekilde uygula.
  • DatabaseStorage.php: Aynı zamanda Storable uygulayan bir DatabaseStorage sınıfı oluştur. Arayüz dosyasını dahil et. Sınıfın, oluşturucu aracılığıyla ayarlanan private bir $tableName özelliği olmalı. save($key, $data) yöntemini "Inserting '[data]' into table [tableName] with key [key]" döndürecek şekilde uygula. retrieve($key) yöntemini "Selecting from table [tableName] where key = [key]" döndürecek şekilde uygula.
  • main.php: Her iki depolama dosyasını dahil et. Bir Storable parametresi, bir anahtar ve veri kabul eden storeData adlı bir işlev oluştur. İşlev, anahtar ve verilerle save() çağrısının sonucunu döndürmeli. Bir Storable parametresi ve bir anahtar kabul eden, retrieve() çağrısının sonucunu döndüren fetchData adlı başka bir işlev oluştur.

Dört girdi alacaksın: bir dizin yolu, bir tablo adı, bir anahtar ve depolanacak bazı veriler. Dizinle bir FileStorage ve tablo adıyla bir DatabaseStorage oluştur. Verileri önce dosya depolamasını, ardından veritabanı depolamasını kullanarak kaydetmek için storeData() işlevini kullan. Her sonucu kendi satırına yazdır. Ardından dosya depolamasından veri almak için fetchData() işlevini kullan ve bu sonucu yazdır.

storeData() ve fetchData() işlevlerinin her iki depolama türüyle de aynı şekilde çalıştığına dikkat et. Bu işlevler yalnızca nesnenin Storable uygulamasını önemser. Dosya sistemi ve veritabanı tamamen farklı dahili uygulamalara sahip olsa da arayüz sözleşmesi sayesinde birbirlerinin yerine kullanılabilirler.

Kendin dene

<?php
require_once 'FileStorage.php';
require_once 'DatabaseStorage.php';

// Girdileri oku
$directory = trim(fgets(STDIN));
$tableName = trim(fgets(STDIN));
$key = trim(fgets(STDIN));
$data = trim(fgets(STDIN));

// TODO: Storable, key ve data kabul eden bir storeData fonksiyonu oluştur
// key ve data ile save() çağrısının sonucunu döndürmelidir

// TODO: Storable ve key kabul eden bir fetchData fonksiyonu oluştur
// key ile retrieve() çağrısının sonucunu döndürmelidir

// TODO: directory ile bir FileStorage örneği oluştur

// TODO: tablo adıyla bir DatabaseStorage örneği oluştur

// TODO: Dosya depolama ile veriyi kaydetmek için storeData() kullan, ardından sonucu yazdır

// TODO: Veritabanı depolama ile veriyi kaydetmek için storeData() kullan, ardından sonucu yazdır

// TODO: Use fetchData() to retrieve from file storage, then print the result
?>
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

Kendi başına pratik yap: Online PHP derleyicisi