Arayüz veya Soyut Sınıf: hangisini kullanmalı?


327

Ne zaman bir PHP kullanmalıyım interfaceve ne zaman bir abstract class?

Nasıl değiştirebilirim abstract classbir karşı in interface?

Yanıtlar:


458

Sisteminizde çalışan geliştiricileri (siz de dahil), oluşturacakları sınıflara belirli sayıda yöntem uygulamaya zorlamak istediğinizde bir arabirim kullanın.

Sisteminizde çalışan geliştiricileri (siz de dahil) belirli sayıda yöntemi uygulamaya zorlamak istediğinizde soyut bir sınıf kullanın ve onlara çocuklarının sınıflarını geliştirmelerine yardımcı olacak bazı temel yöntemler sunmak istiyoruz.

Akılda tutulması gereken başka bir şey, istemci sınıflarının yalnızca bir soyut sınıfı genişletebileceği, oysa birden fazla arabirim uygulayabileceğidir. Dolayısıyla, davranış sözleşmelerinizi soyut sınıflarda tanımlıyorsanız, bu her çocuk sınıfının yalnızca tek bir sözleşmeye uygun olabileceği anlamına gelir. Bazen, kullanıcı programcılarınızı belirli bir yol boyunca zorlamak istediğinizde bu iyi bir şeydir. Diğer zamanlarda kötü olurdu. PHP'nin Sayılabilir ve Yineleyici arabirimlerinin arabirimler yerine soyut sınıflar olup olmadığını düşünün.

Hangi yoldan gideceğinizden emin değilseniz yaygın olan bir yaklaşım ( aşağıda cletus tarafından belirtildiği gibi ) bir arayüz oluşturmak ve daha sonra soyut sınıfınızın bu arayüzü uygulamasını sağlamaktır.


12
Bütün gün kullanımlarını abstractve interfacesınıflarını anlamaya çalışıyordum , yazınız her şeyi açıklığa kavuşturdu. Çok teşekkürler Alan
afarazit

4
Soyut sınıfların bir diğer avantajı, soyut korumalı yöntemleri tanımlama yeteneğidir . Her zaman kullanışlı değildir, ancak bazı mimarilerde kullanışlı olabilir.
netcoder

Birçok durumda esneklik nedeniyle soyut sınıfı kullanmalıyız - bu benim sonucum :)
ymakux

3
@volocuga: Alan'ın belirttiği gibi, sadece tek bir özet uzatılabilir. Ben şahsen soyut bir arayüz fikri uygular sevmiyorum çünkü kod gizlemeye katkıda bulunur ve daha az doğrudan, IMO.
Önek

171

An Abstract Classve an arasındaki farklar Interface:

Soyut Sınıflar

Soyut bir sınıf bazı işlevler sağlayabilir ve geri kalanını türetilmiş sınıf için bırakabilir .

  • Türetilmiş sınıf , temel sınıfta tanımlanan somut fonksiyonları geçersiz kılabilir veya geçersiz kılabilir .

  • Soyut bir sınıftan genişletilmiş bir çocuk sınıfı mantıksal olarak ilişkili olmalıdır.

Arayüz

Bir arabirim herhangi bir işlev içeremez . O sadece yöntemlerin tanımlarını içerir.

  • Türetilmiş sınıf , arabirimde tanımlanan tüm yöntemler için kod SAĞLAMALIDIR .

  • Tamamen farklı ve ilişkili olmayan sınıflar bir arabirim kullanılarak mantıksal olarak birlikte gruplandırılabilir.


1
Bunu göstermek için gerçek bir hayat örneği verebilir misiniz?
RN Kushwaha

1
Nedir arasındaki fark abstract class X implements Yve class X implements Y?
Webinan

3
@Webinan abstract class X implements YX'in toplu işlevselliğinin türetilmiş bir sınıfta uygulanması gerektiğini ve hem soyut hem de türetilmiş sınıfın Y'de tanımlanan işlevleri içermesi gerektiğini belirtirken, class X implements Yyalnızca X sınıfının Y'de tanımlanan işlevleri içermesi gerektiğini belirtirsiniz. XI, aslında Y'nin bir arabirim olarak tanımlanmasını atlamayacak ve yalnızca Y'deki işlevleri türetici sınıfta uygulandıklarından emin olmak için genel / korumalı / özel soyut işlev olarak uygulayacağından başka bir sınıf tarafından uygulanması amaçlanmamıştır.
Calle Bergström

1
Arayüzler sadece yöntemlerin tanımını içeremez, aynı zamanda sabitler
Thielicious

Karşılaştırmanızı beğendim. Yani bir şey eklemek istedim. Soyut sınıf olamazken, arayüzler sınıf sabitlerini kutudan çıkarabilir.
Noman Ibrahim

128

Soyut sınıflar neden kullanılmalı? Aşağıdaki basit bir örnektir. Diyelim ki şu kodumuz var:

<?php 

class Fruit {
    private $color;

    public function eat() {
        // chew
    }

    public function setColor($c) {
        $this->color = $c;
    }
}

class Apple extends Fruit {
    public function eat() {
        // chew until core
    }
}

class Orange extends Fruit {
    public function eat() {
        // peeling
        // chew
    }
}

Şimdi sana bir elma veriyorum ve sen yiyorsun. Tadı nasıl? Elma gibi tadı var.

<?php 
$apple = new Apple();
$apple->eat();

// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();

Bu tat neye benziyor? Pek mantıklı değil, bu yüzden bunu yapamamanız gerekir. Bu, Fruit sınıfını ve içindeki eat yöntemini soyut yaparak başarılır.

<?php 
abstract class Fruit {
    private $color;

    abstract public function eat(){}

    public function setColor($c) {
        $this->color = $c;
    }
}
?>

Soyut bir sınıf bir arayüz gibidir, ancak bir soyut sınıfta yöntemleri tanımlayabilirken, bir arayüzde hepsi soyuttur. Soyut sınıflar hem boş hem de çalışma / somut yöntemlere sahip olabilir. Arayüzlerde, burada tanımlanan fonksiyonların bir gövdesi olamaz. Soyut sınıflarda, yapabilirler.

Gerçek bir dünya örneği:

<?php 
abstract class person {

    public $LastName;
    public $FirstName;
    public $BirthDate;

    abstract protected function write_info();
}

final class employee extends person{

    public $EmployeeNumber;
    public $DateHired;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";   
    }
}

final class student extends person{

    public $StudentNumber;
    public $CourseName;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
    }
}

///----------
$personA = new employee;
$personB = new student;

$personA->FirstName="Joe";
$personA->LastName="Sbody";

$personB->FirstName="Ben";
$personB->LastName="Dover";

$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table 

2
Merhaba, bu cevap muhtemelen biçimlendirilme biçimi nedeniyle aşağı oy aldı. Büyük bir kod bloğu olmasaydı iyi olurdu (dört boşluk bir kod bloğuna bir şey yapar, metni bloktan çıkarmak için girintisiz) ve bu bir yerden kopyalanmışsa (öyle görünüyor) onlara kredi vermek kibar olurdu.
Camilo Martin

9
Meyve örnek adamı için seni seviyorum! Ben php öğrenmeye başladığımdan beri, Bu exmaples bana çok teşekkürler netleştirir
Raheel

23
+1 What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.Artık soyut biliyorum!
Webinan

Ne geliyor finalanahtar kelimeye? Harika gönderi, teşekkürler.
Gus

1
@VineeshKalarickal Kişi örneğinde anlamadığım şey: 1) soyut sınıf Personeli kullanma (örnekte olduğu gibi); 2) Kişiyi standart bir sınıf olarak yazmak ve Çalışan ve Öğrenci yapmak write_info () yöntemini geçersiz kılar.
Ferex

66

En iyi uygulama, sözleşmeyi ve soyut bir sınıfı belirtmek için bir arayüz kullanmaktır. Bu soyut sınıf, çok sayıda kazan plakasını doldurabilir, böylece sadece belirli bir uygulamayı kullanmaya zorlamadan ihtiyacınız olan veya istediğiniz şeyi geçersiz kılarak bir uygulama oluşturabilirsiniz.


37

Sadece bunu karışıma atmak için, ancak Cletus'un soyut bir sınıfla birlikte bir arayüz kullanarak bahsettiği gibi, genellikle tasarım düşünümü netleştirmek için arayüzü kullanırım.

Örneğin:

<?php
class parser implements parserDecoratorPattern {
    //...
}

Bu şekilde, kodumu okuyan (ve bir Dekoratör Deseninin ne olduğunu bilen) hemen bilecek olan a) ayrıştırıcımı nasıl oluşturduğumu ve b) dekoratör desenini uygulamak için hangi yöntemlerin kullanıldığını görebilecektir.

Ayrıca, burada bir Java / C ++ / etc programcısı olmamak için temelden uzak olabilirim, ancak veri türleri burada devreye girebilir. Nesneleriniz bir türdendir ve nesnelerin etrafından geçirdiğinizde programlı olarak önemlidir. Anlaşılabilir öğelerinizi arayüze taşımak, yalnızca yöntemlerin döndürdüğü türleri belirler, ancak onu uygulayan sınıfın temel türünü değil.

Geç oldu ve daha iyi bir psudo-code örneği düşünemiyorum, ama işte gidiyor:

<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)

1
Ne harika bir örnek! ;)
Joel Murphy

@ matt2000 Cinsiyetçi değil VE şimdi de eşcinsel evlilikler için çalışıyor. Harika düzenleme. :)
Austen Hoogen

4
Bu harika bir örnek! Ancak, soyut bir sınıfı somutlaştırabileceğinizi değil, soyut bir sınıftan uzanan bir sınıfı düşünüyorum
Arielle Nguyen

2
sudo kodunu en azından söz konusu dile benzetmek için öldürmezdim. Birisi oraya bir kaç dolar koymalý.
Bir ayı güreştim.

2
Örnek komik olsa da, soyut bir sınıfı doğrudan başlatamayız, lütfen örnekte değişiklikler yapın, böylece insanlar onu PHP'de geçerli kullanım olarak görmeyebilir.
saji89

16

Temel fark, soyut bir sınıfın varsayılan uygulamayı içerebileceği, ancak arabirimin yapamayacağıdır.

Arayüz, herhangi bir uygulama olmadan davranış sözleşmesidir.


16

Ayrıca, sadece diğer herhangi bir OO dilinin bir tür arayüzlere ve soyutlamaya da sahip olması, PHP'dekiyle aynı anlama ve amaca sahip oldukları anlamına gelmediğini buraya eklemek isterim. Soyutlama / arayüzlerin kullanımı biraz farklıdır, ancak PHP'deki arayüzlerin gerçek bir işlevi yoktur. Sadece semantik ve şema ile ilgili nedenlerle kullanılırlar. Mesele, geliştiricinin tamamen farklı bir kullanım planına sahip olup olmadığına bakılmaksızın, gelecekteki uzantılar için mümkün olduğunca esnek, genişletilebilir ve güvenli bir projeye sahip olmaktır.

İngilizceniz yerli değilse, Soyutlama ve Arayüzlerin gerçekte ne olduğunu araştırabilirsiniz. Ve eşanlamlıları da arayın.

Ve bu bir metafor olarak size yardımcı olabilir:

ARAYÜZ

Diyelim ki, çilek ile yeni bir çeşit kek pişiriyorsunuz ve malzemeleri ve adımları açıklayan bir tarif hazırladınız. Neden sadece bu kadar lezzetli olduğunu ve misafirlerinizin bunu sevdiğini biliyorsunuz. Sonra diğer insanların da bu pastayı deneyebilmesi için tarifinizi yayınlamaya karar verdiniz.

Buradaki nokta

- doğru yapmak
- dikkatli olmak
- kötü gidebilecek şeyleri önlemek için (çok fazla çilek ya da bir şey gibi)
- deneyen insanlar için kolay tutmak
- ne yapacağınızı (karıştırmak gibi) söylemek )
- hangi şeyleri yapabileceğinizi söylemek zorundasınız

Tam olarak BU, arayüzleri tanımlayan şeydir. Bu bir rehber, tarifin içeriğini gözlemleyen bir dizi talimattır. PHP'de bir proje yaratırsınız ve GitHub'da veya arkadaşlarınızla ya da her neyse kodu sağlamak istersiniz. Bir arayüz insanların yapabilecekleri ve yapmamanız gereken şeydir. Onu tutan kurallar - birine uymazsanız, tüm yapı kırılacaktır.


SOYUTLAMA

Bu metaforla devam etmek için ... hayal edin, bu sefer o pastayı yiyen misafirsiniz. O zaman şimdi tarifi kullanarak o pastayı deniyorsun. Ancak yeni malzemeler eklemek veya tarifte açıklanan adımları değiştirmek / atlamak istiyorsunuz. Peki sırada ne var? O pastanın farklı bir versiyonunu planlayın. Bu kez siyah meyveler ve saman meyveleri ve daha vanilyalı krema ile ... nefis.

Orijinal pastanın bir uzantısı olarak düşünebilirsiniz. Temelde yeni bir tarif oluşturarak bir soyutlama yapıyorsunuz çünkü bu çok farklı. Birkaç yeni adımı ve diğer malzemeleri var. Bununla birlikte, siyah dut versiyonunun orijinalinden aldığınız bazı parçaları vardır - bunlar o pastanın her türünün sahip olması gereken temel adımlardır. Tıpkı süt gibi malzemeler gibi - Her türetilmiş sınıfın sahip olduğu budur.

Şimdi malzemeleri ve adımları değiştirmek istiyorsunuz ve bunlar o pastanın yeni versiyonunda tanımlanmalı ZORUNLU. Bunlar yeni kek için tanımlanması gereken soyut yöntemlerdir , çünkü kekin içinde bir meyve olmalı ama hangisi? Yani bu sefer siyah meyveleri alıyorsunuz. Bitti.

İşte, pastayı uzattınız, arayüzü takip ettiniz ve ondan soyutlanmış adımlar ve malzemeler aldınız.


1
Bu PHP ile ilgili bir şey benim favori karşılaştırma oldu. Gerçekten mantıklı. Teşekkür ederim!
cbloss793

13

Zaten mükemmel cevapların bazılarına eklemek için:

  • Soyut sınıflar bir derece uygulama sağlar, arayüzler saf şablonlardır. Bir arayüz sadece işlevselliği tanımlayabilir , asla uygulayamaz.

  • Arabirimi uygulayan her sınıf, tanımladığı tüm yöntemleri uygulamayı taahhüt eder veya özet olarak bildirilmelidir.

  • Arayüzler, Java gibi PHP'nin birden fazla mirası desteklemediğini yönetmeye yardımcı olabilir. Bir PHP sınıfı yalnızca tek bir üst öğeyi genişletebilir. Ancak, istediğiniz kadar çok arabirimi uygulamak için bir sınıf sözü verebilirsiniz.

  • type: uyguladığı her arabirim için sınıf ilgili türü alır. Herhangi bir sınıf bir arabirim (veya daha fazla arabirim) uygulayabileceğinden, arabirimler başka türlü ilgisiz türlere etkin bir şekilde katılır.

  • bir sınıf hem bir üst sınıfı genişletebilir hem de istediğiniz sayıda arabirimi uygulayabilir:

    class SubClass extends ParentClass implements Interface1, Interface2 {
        // ...
    }

Lütfen ne zaman bir arayüz kullanmalıyım ve ne zaman soyut sınıf kullanmalıyım?

Yalnızca hiç uygulama içermeyen bir şablon sağlamanız gerektiğinde bir arabirim kullanın ve bu arabirimi uygulayan herhangi bir sınıfın onu uygulayan diğer sınıflarla aynı yöntemlere sahip olduğundan emin olmak istediğinizde (en azından).

Diğer nesneler (kısmen oluşturulmuş bir sınıf) için temel oluşturmak istediğinizde soyut bir sınıf kullanın. Soyut sınıfınızı genişleten sınıf, tanımlanan / uygulanan bazı özellikleri veya yöntemleri kullanır:

<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

Soyut sınıfımı bir arayüze nasıl değiştirebilirim?

İşte basitleştirilmiş bir örnek / örnek. Uygulama ayrıntılarını çıkarın. Örneğin, soyut sınıfınızı şununla değiştirin:

abstract class ClassToBuildUpon {
    public function doSomething() {
          echo 'Did something.';
    }
}

için:

interface ClassToBuildUpon {
    public function doSomething();
}

12

Felsefi açıdan:

  • Soyut bir sınıf bir "eşittir" ilişkisini temsil eder. Diyelim ki meyvelerim var, ortak sorumlulukları ve ortak davranışları paylaşan bir meyve soyut sınıfım olacaktı.

  • Bir arayüz "yapmalı" ilişkisini temsil eder. Bence bir arayüz (bir junior dev'in görüşüdür), bir eylem veya bir eyleme yakın bir şeyle adlandırılmalıdır, (Üzgünüm, kelimeyi bulamıyorum, İngilizce ana dili konuşanı değilim) IEatable diyelim. Yenilebileceğini biliyorsunuz, ama ne yediğinizi bilmiyorsunuz.

Kodlama açısından:

  • Nesnelerinizde çoğaltılmış kod varsa, ortak davranışa sahip olduklarının bir göstergesidir, yani kodu yeniden kullanmak için bir arabirimle yapamayacağınız soyut bir sınıfa ihtiyacınız olabilir.

  • Bir başka fark, bir nesnenin ihtiyacınız olduğu kadar çok arabirim uygulayabilmesidir, ancak "elmas sorunu" nedeniyle yalnızca bir soyut sınıfa sahip olabilirsiniz (nedenini öğrenmek için buraya göz atın! Http://en.wikipedia.org/wiki/ Çoklu_geliş # The_diamond_problem )

Muhtemelen bazı noktaları unutuyorum ama umarım bazı şeyleri açıklığa kavuşturabilir.

Not: "bir" / "yapmalı" Vivek Vermani'nin cevabı tarafından getirildi, cevabını çalmak istemedim, sadece terimleri tekrar kullanmak için onları sevdim çünkü!


2
Aradığınız kelime yenilebilir, inanıyorum.
Travis Weston

1
Aslında, onun bir "Fiil", bir "yapıyor kelime"
inanıyorum

7

Soyut bir sınıf ve bir arayüz arasındaki teknik farklar, diğer cevaplarda tam olarak listelenmiştir. Nesne yönelimli programlama uğruna kod yazarken bir sınıf ve bir arayüz arasında seçim yapmak için bir açıklama eklemek istiyorum.

Bir sınıf bir varlığı temsil ederken, bir arayüz davranışı temsil etmelidir.

Bir örnek verelim. Bilgisayar monitörü bir varlıktır ve bir sınıf olarak temsil edilmelidir.

class Monitor{
    private int monitorNo;
}

Size bir ekran arayüzü sağlamak için tasarlanmıştır, bu nedenle işlevsellik bir arayüz tarafından tanımlanmalıdır.

interface Display{
    void display();
}

Diğer cevaplarda açıklandığı gibi düşünülmesi gereken birçok şey var, ancak bu kodlama sırasında çoğu insanın görmezden geldiği en temel şey.


2
PHP dönüş türlerini tanımlamaz ve OP bu soruyu şu şekilde etiketlediPHP
Purefan

1

Her ikisini de ne zaman kullanmanız gerektiğine dair bir örnek eklemek istedim. Şu anda genel amaçlı ERP çözümünde bir veritabanı modeline bağlı bir dosya işleyicisi yazıyorum.

  • Standart crud ve farklı dosya kategorileri için dönüşüm ve akış gibi bazı özel işlevsellik işlemek çoklu soyut sınıfları var.
  • Dosya erişim arabirimi, bir dosyayı almak, depolamak ve silmek için gereken yaygın bir yöntem kümesini tanımlar.

Bu şekilde, farklı dosyalar için birden fazla şablon ve net bir ayrım ile ortak bir arayüz yöntemleri setine sahip olurum. Arayüz, temel bir soyut sınıfla olanlardan ziyade erişim yöntemlerine doğru benzetme sağlar.

Dahası, farklı dosya depolama hizmetleri için adaptörler yapacağım zaman, bu uygulama, arayüzün tamamen farklı bağlamlarda başka bir yerde kullanılmasına izin verecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.