Skip to content

6. Arayüzler

Bir arayüz, yöntem prototiplerini tanımlayan bir yapıdır. Bir arayüzü uygulayan bir sınıf, arayüzdeki tüm yöntemlerin kodunu tanımlamalıdır.

6.1. Komut dosyalarının ağaç yapısı

Image

6.2. İlk arayüz

[IExemple.php] adlı bir komut dosyasında [IExemple] adlı bir arayüz tanımlıyoruz. Aynı komut dosyasında, [IExemple] arayüzünü uygulayan iki sınıf tanımlıyoruz:


<?php

// fonksiyon parametrelerinin türlerine sıkı uyumu
declare(strict_types=1);

// ad alanı
namespace Exemples;

// bir arayüz
interface IExemple {
    // arayüzün yöntemleri
    public function ajouter(int $i, int $j): int;
    public function soustraire(int $i, int $j): int;
}

// arayüzün 1. uygulaması IExemple
class Classe1 implements IExemple {
    public function ajouter(int $a, int $b): int {
        return $a + $b + 10;
    }

    public function soustraire(int $a, int $b): int {
        return $a - $b + 20;
    }

}

// IExemple arayüzünün 2. uygulaması
class Classe2 implements IExemple {
    public function ajouter(int $a, int $b) : int{
        return $a + $b + 100;
    }

    public function soustraire(int $a, int $b) : int {
        return $a - $b + 200;
    }

}

Açıklamalar

  • 10-14. satırlar: IExemple arayüzü iki yöntem tanımlar: ajouter işlevi (12. satır) ve soustraire işlevi (13. satır). Arayüz, bu yöntemlerin kodunu tanımlamaz. Bunu, arayüzü uygulayan sınıflar yapar;
  • 17. satır: Classe1 sınıfı, IExemple arayüzünü uygular (implements). Dolayısıyla, ajouter (satır 18) ve soustraire (satır 22) yöntemleri için bir kod tanımlar;
  • 29-38. satırlar: Classe2 sınıfı için de durum aynıdır;

Aşağıdaki [interfaces-01.php] betiğinde [IExemple] arayüzünü kullanıyoruz:


<?php

require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;

// fonksiyon
function calculer(int $a, int $b, IExemple $interface) : void {
  print $interface->ajouter($a, $b)."\n";
  print $interface->soustraire($a, $b)."\n";
}

// ------------------- ana işlev
// Classe1 ve Classe2 türünde 2 nesnenin oluşturulması
$c1 = new Classe1();
$c2 = new Classe2();
// calculer işlevinin çağrılması
calculer(4, 3, $c1);
calculer(14, 13, $c2);

Yorumlar

  • 3-6. satırlar: komut dosyası tarafından kullanılan sınıfların ve arayüzlerin dahil edilmesi ve tanımlanması;
  • 3. satır: include komutu yerine burada require_once komutunu kullandık. "include" komutu, bir dosya daha önce dahil edilmiş olsa bile onu mevcut komut dosyasına dahil ederken, "require_once" komutu ise dosyayı yalnızca bir kez dahil eder. Dolayısıyla kod dahil etme konusunda "require_once" komutunu tercih ederiz;
  • 9-12. satırlar: bir işlev tanımlıyoruz;
  • 9. satır: Burada üç parametrenin türünü bildirmişiz. Yürütme sırasında, etkin parametre beklenen türde değilse bir hata atılır. 3. parametre [IExemple] türündedir. Bu, etkin parametrenin [IExemple] arayüzünü uygulayan bir sınıfın örneği olması gerektiği anlamına gelir; dolayısıyla örneğimizde, [Classe1] veya [Classe2] sınıflarının bir örneği olmalıdır;
  • 10-11. satırlar: [IExemple] arayüzünün [ajouter, soustraire] yöntemlerini kullanıyoruz;
  • 19. satır: 3. etkin parametre, fonksiyonun 3. biçimsel parametresinin [IExemple] türüyle uyumlu olan [Classe1] türündedir;
  • 20. satır: [Classe2] sınıfı için de durum aynıdır;

Sonuçlar

1
2
3
4
17
21
127
201

6.3. Bir arayüzün türetilmesi

Bir alt sınıfın bir üst sınıfı genişletebileceği gibi, bir alt arayüz de bir üst arayüzü genişletebilir.

[IExemple2.php] dosyasında tanımlanan [IExemple2] arayüzünü ele alalım:


<?php

// fonksiyon parametrelerinin türlerine sıkı sıkıya uyulması
declare(strict_types=1);
// ad alanı
namespace Exemples;

// IExemple arayüzünün tanımının dahil edilmesi
require_once __DIR__."/IExemple.php";

// IExemple'ten türetilen bir arayüz
interface IExemple2 extends IExemple {
    // arayüzün yöntemi
    public function multiplier(int $i, int $j): int;
}

// IExemple2 arayüzünün uygulaması
class Classe3 extends Classe2 implements IExemple2 {
   
    public function multiplier(int $a, int $b): int {
        return $a * $b;
    }

}

Açıklamalar

  • 6. satır: [IExemple2] arayüzü, [Iexemple] arayüzüyle aynı ad alanında olacaktır;
  • 9. satır: [Iexemple] arayüzünün tanım dosyası eklenir;
  • 12-15. satırlar: [Iexemple] arayüzünü genişleten (miras alan) ve ona yeni bir yöntem ekleyen (14. satır) [IExemple2] arayüzünü tanımlar;
  • satır 18-24: [Classe3] sınıfı, [Classe2] sınıfını genişletir. Bu sınıf, [IExemple] arayüzünü uyguladığı için, [Classe3] sınıfı da aynı şekilde bu arayüzü uygulayacaktır. Nitekim, [Classe3] sınıfı, [Classe2] sınıfının tüm public ve protected yöntemlerini miras alır; dolayısıyla "ekle" ve "çıkar" yöntemlerini de miras alır. Ayrıca, [Classe3] sınıfının [IExemple2] arayüzünü uyguladığı belirtilmektedir. Bu nedenle, bu sınıf aynı zamanda “multiplier” yöntemini de uygulamalıdır; ancak [Classe2] sınıfı bunu yapmamaktadır. 20-22. satırlarda bu işlem gerçekleştirilmektedir;

[IExemple2] arayüzü, aşağıdaki [interfaces-02] komut dosyası tarafından kullanılır:


<?php

// fonksiyon parametrelerinin türlerine sıkı bir şekilde uyulması
declare(strict_types=1);

// komut dosyası için gerekli sınıf ve arayüzlerin dahil edilmesi ve nitelendirilmesi
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;

// fonksiyon
function calculer(int $a, int $b, IExemple2 $interface) {
    print $interface->ajouter($a, $b) . "\n";
    print $interface->soustraire($a, $b) . "\n";
    print $interface->multiplier($a, $b) . "\n";
}

// ------------------- main
// IExemple2'i uygulayan Classe3 türünde 1 nesnenin oluşturulması
$c3 = new Classe3();
// calculer işlevinin çağrılması
calculer(4, 3, $c3);

Açıklamalar

  • 12. satır: [calculer] işlevinin 3. parametresi [IExemple2] türündedir;
  • 13-15. satırlar: [IExemple2] arayüzünün üç yöntemi kullanılır;
  • 22. satır: [calculer] işlevi, 3. parametre olarak [IExemple2] türünde bir nesne (20. satır) ile çağrılır;

Sonuçlar

1
2
3
107
201
12

6.4. Bir arayüzün işlev parametresi olarak aktarılması

Bir önceki paragrafta, bir fonksiyon parametresi için beklenen tür bir sınıf olduğunda, fiili parametrenin beklenen türden veya türetilmiş bir nesne olabileceğini görmüştük. Aşağıdaki [interfaces-03.php] komut dosyasında gösterildiği gibi, bu durum arayüzler için de geçerlidir:


<?php

// fonksiyon parametrelerinin türlerine sıkı sıkıya uyulması
declare(strict_types=1);

// komut dosyası için gerekli sınıf ve arayüzlerin dahil edilmesi ve nitelendirilmesi
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;

// fonksiyon
function calculer(int $a, int $b, IExemple $interface) {
  print $interface->ajouter($a, $b) . "\n";
  print $interface->soustraire($a, $b) . "\n";
}

// ------------------- main
// IExemple2'i ve dolayısıyla IExemple'i uygulayan Classe3 türünde 1 nesne oluşturma
$c3 = new Classe3();
// calculer işlevinin çağrılması
calculer(4, 3, $c3);

Açıklamalar

  • 13. satırda, [calculer] fonksiyonu üçüncü parametre olarak [IExemple] türünü beklemektedir. Bu, fiili parametrenin türünün [IExemple] veya türetilmiş bir tür olabileceği anlamına gelir;
  • 20. satır: [Classe3] türünde bir $c3 nesnesi oluşturuluyor; bu sınıf, [IExemple2] arayüzünü uyguluyor ve bu arayüz de [IExemple] arayüzünü genişletiyor. Dolayısıyla sonuç olarak $c3, [IExemple] arayüzünü uygular;
  • 22. satır: [calculer] işlevi, üçüncü parametre olarak [Classe3] türünde bir $c3 nesnesi ile çağrılır. Sınıf mirasları ve uygulamalar sayesinde, $c3 nesnesinin [IExemple] türünü uyguladığını gördük. Dolayısıyla bunu üçüncü parametre olarak kullanabiliriz;

Sonuçlar

107
201