1. Einleitung
Interfaces besitzen eine gewisse Ähnlichkeit mit abstrakten Klassen. Auch Interfaces können nicht instanziiert werden und dürfen Methoden beinhalten, die keine Implementierung haben, bei denen also nur Name und Parameter vorgegebeben sind. Genauer: Sie dürfen sogar nur solche abstrakten Methoden enthalten! Weiterhin dürfen Klassen mehrere Interfaces gleichzeitig implementieren und müssen jedes implementierte Interface über implements Interfacename kenntlich machen (statt wie bei abstrakten Klassen über extends Klassenname).
Sinn von Interfaces ist es, ein besonders hohes Maß an Abstraktion zu ermöglichen. So könnte ein Interface „Positioned” definiert werden, welches vorschreibt, dass jede Klasse, die das Interface implementiert, eine Methode getCoordinates() anbieten muss über die die Koordinaten des Objekts ermittelt werden können. Dieses Interface könnte von völlig verschiedenen Klassen implementiert werden: Flugzeuge, Autos, Häuser, Personen etc. Andere Klassen, die mit Objekten arbeiten wollen, die eine Position haben, müssten dann nur noch vorgeben, dass das übergebene Objekt des Interface „Positioned” implementieren muss. Aufgrund dieser Flexibilität gilt es als guter Stil, seine eigenen Klassen möglichst so zu implementieren, dass sie von Interfaces und nicht von bestimmten (Eltern-)Klassen abhängig sind.
2. Beispiel: Haustier-Interface
In diesem Beispiel wird ein Interface „IHaustier” definiert. Dieses schreibt vor, dass das Haustier eine Methode getName() anbieten muss. Andere Klassen, die mit Haustieren arbeiten wollen, können sich dann darauf verlassen, dass das Haustier einen Namen anbietet (vorausgesetzt es implementiert das Interface). Es werden die zwei Klassen „Hund” und „VirtuelleKatze” definiert, welche jeweils „IHaustier” implementieren. Während dem Hund schon im Konstruktor ein Name übergeben wird, erhält die virtuelle Katze seinen Namen automatisch zugewiesen (hier über eine Zufallsauswahl aus einer Menge von möglichen Namen). Trotz dieses Unterschieds bei der Namensvergabe können sich alle anderen Klasse darauf verlassen, dass jedes Objekt der Klassen „Hund” und „VirtuelleKatze” einen Namen anbietet, da beide das Interface IHaustier implementieren.
<?php /** * Ein Interface für Haustiere. Jedes * Haustier soll einen Namen haben, der über getName() abgerufen werden kann. * Das "I" vor "Haustier" deutet an, dass es sich um ein Interface handelt. */ interface IHaustier { // Die Methode wird über das Interface nur vorgeschrieben, // daher darf sie keinen Inhalt haben. public function getName(); } /** * Die Klasse Hund. * Für jeden Hund darf ein Name festgelegt werden. Über getName() * kann er - entsprechend der Vorschrift von IHaustier - abgefragt werden. */ class Hund implements IHaustier { private $name; public function __construct($name) { $this->name = $name; } // Die vom Interface IHaustier verlangte Methode public function getName() { return $this->name; } } /** * Klasse für eine virtuelle Katze. Es soll hier kein Name * beim Erzeugen eines Objekts festgelegt werden, stattdessen wird zufällig einer * ausgewählt. Die Methode getName() muss dennoch in jedem Fall angeboten werden, da die Klasse * Interface IHaustier einbindet. */ class VirtuelleKatze implements IHaustier { private $name; public function __construct() { $names = array('Tigger', 'CyberKatze', 'Mauzer', 'Mausejäger'); shuffle($names); $this->name = array_pop($names); } // Die vom Interface IHaustier verlangte Methode public function getName() { return $this->name; } } $einHund = new Hund('Rex'); $vKatze = new VirtuelleKatze(); var_dump($einHund->getName()); var_dump($vKatze->getName()); ?>
string(3) "Rex" string(6) "Tigger"
Kommentare (1)
Von neu nach altWir bitten um ihr Verständnis.