374 Stimmen

Schnittstelle oder abstrakte Klasse: was ist zu verwenden?

Bitte erklären Sie mir, wann ich ein PHP-Programm verwenden sollte interface und wann sollte ich eine abstract class ?

Wie ich mein Leben ändern kann abstract class in eine interface ?

512voto

Alan Storm Punkte 160579

Verwenden Sie eine Schnittstelle, wenn Sie Entwickler, die in Ihrem System arbeiten (Sie selbst eingeschlossen), zwingen wollen, eine bestimmte Anzahl von Methoden in den Klassen zu implementieren, die sie erstellen werden.

Verwenden Sie eine abstrakte Klasse, wenn Sie Entwickler, die in Ihrem System arbeiten (Sie selbst eingeschlossen), zwingen wollen, eine bestimmte Anzahl von Methoden zu implementieren Sie möchten einige Basismethoden bereitstellen, die ihnen bei der Entwicklung ihrer Unterklassen helfen.

Zu beachten ist auch, dass Client-Klassen nur eine abstrakte Klasse erweitern können, während sie mehrere Schnittstellen implementieren können. Wenn Sie also Ihre Verhaltensverträge in abstrakten Klassen definieren, bedeutet dies, dass jede untergeordnete Klasse nur einem einzigen Vertrag entsprechen kann. Manchmal ist dies eine gute Sache, wenn Sie Ihre Benutzerprogrammierer auf einen bestimmten Weg zwingen wollen. In anderen Fällen wäre es schlecht. Stellen Sie sich vor, die PHP-Schnittstellen Countable und Iterator wären abstrakte Klassen anstelle von Schnittstellen.

Ein üblicher Ansatz, wenn Sie unsicher sind, welchen Weg Sie einschlagen sollen (wie von Cletus unten ) ist es, eine Schnittstelle zu erstellen und diese dann von Ihrer abstrakten Klasse implementieren zu lassen.

195voto

kn3l Punkte 18187

Die Unterschiede zwischen einer Abstract Class und ein Interface :

Abstrakte Klassen

Eine abstrakte Klasse kann einige Funktionen bereitstellen y den Rest der abgeleiteten Klasse überlassen .

  • Die abgeleitete Klasse kann, muss aber nicht Vorrang haben vor die in der Basisklasse definierten konkreten Funktionen.

  • Eine Kindklasse, die von einer abstrakten Klasse erweitert wird, sollte logisch verwandt sein.

Schnittstelle

Eine Schnittstelle darf keine Funktionalität enthalten . Sie sólo enthält Definitionen der Methoden.

  • Die abgeleitete Klasse MUSS Code für alle in der Schnittstelle definierten Methoden bereitstellen .

  • Völlig unterschiedliche und nicht verwandte Klassen können über eine Schnittstelle logisch zusammengefasst werden.

146voto

Vineesh Kalarickal Punkte 3191

Warum sollte man abstrakte Klassen verwenden? Das folgende ist ein einfaches Beispiel. Nehmen wir an, wir haben den folgenden Code:

<?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
    }
}

Jetzt gebe ich dir einen Apfel und du isst ihn. Wie schmeckt er? Er schmeckt wie ein Apfel.

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

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

Wie schmeckt das? Nun, es macht nicht viel Sinn, also solltest du das nicht tun können. Dies wird erreicht, indem die Klasse Fruit und die darin enthaltene Methode eat abstrakt gemacht werden.

<?php 
abstract class Fruit {
    private $color;

    abstract public function eat(){}

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

Eine abstrakte Klasse ist genau wie eine Schnittstelle, aber Sie können in einer abstrakten Klasse Methoden definieren, während sie in einer Schnittstelle alle abstrakt sind. Abstrakte Klassen können sowohl leere als auch funktionierende/konkrete Methoden haben. In Schnittstellen können die dort definierten Funktionen keinen Körper haben. In abstrakten Klassen können sie das.

Ein Beispiel aus der Praxis:

<?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

78voto

cletus Punkte 596503

Am besten ist es, eine Schnittstelle zu verwenden, um den Vertrag zu spezifizieren, und eine abstrakte Klasse als nur eine Implementierung davon. Diese abstrakte Klasse kann einen großen Teil der Boilerplate ausfüllen, so dass Sie eine Implementierung erstellen können, indem Sie einfach überschreiben, was Sie brauchen oder wollen, ohne dass Sie gezwungen sind, eine bestimmte Implementierung zu verwenden.

40voto

Austen Hoogen Punkte 2516

Wie Cletus bereits erwähnt hat, verwende ich die Schnittstelle oft in Verbindung mit einer abstrakten Klasse, um mein Designdenken zu verdeutlichen.

Zum Beispiel:

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

Auf diese Weise wird jeder, der meinen Code liest (und weiß, was ein Decorator Pattern ist), sofort wissen, a) wie ich meinen Parser aufbaue und b) in der Lage sein zu sehen, welche Methoden verwendet werden, um das Decorator Pattern zu implementieren.

Außerdem kann es sein, dass ich hier falsch liege, da ich kein Java/C++/etc-Programmierer bin, aber Datentypen können hier ins Spiel kommen. Ihre Objekte sind von einem Typ, und wenn Sie sie weitergeben, ist der Typ programmatisch wichtig. Das Verschieben Ihrer kontrahierbaren Elemente in die Schnittstelle diktiert nur die Typen, die die Methoden zurückgeben, aber nicht den Basistyp der Klasse, die sie implementiert.

Es ist schon spät, und mir fällt kein besseres Beispiel für psudo-Code ein, aber hier ist es:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X