Interfaces

Interfaces - Schnittstellen einer Klasse

Bislang wurde das Konzept der Vererbung sowie abstrakte Klassen vorgestellt. Bei der Vererbung ist es so, dass eine Klasse immer nur von einer anderen Klasse erben kann. Deshalb ist die Vererbung ein sehr mächtiges Konzept.

Es gibt Situationen, in denen man sicherstellen möchte, dass eine Klasse eine bestimmte Methode implementiert, aber man kann diese Klasse nicht von einer Objekt erben lassen, da es entweder keinen Sinn macht, oder die Klasse schon von einem anderen Objekt erbt.


Zu diesem Zweck gibt es Interfaces. Ein Interface legt eine Schnittstelle fest. Jede Klasse die ein Interface implementiert, muss die Methoden des Interfaces bereitstellen.


Beispiel:

Für eine Routenberechnung gibt es verschiedene Ziele. Zum einen können dies Adressen von Personen sein, aber auch Adressen von Firmen oder Sehenswürdigkeiten. Alle haben als gemeinsame Eigenschaft eine Adresse. Es ist jedoch „Verschwendung“ das Personen Objekt und das Firmen Objekt von einem Adresseobjekt erben zu lassen. Ausserdem währe es auch semantisch falsch, da man nicht sagen kann „Eine Person ist eine Adresse“

Für diesen Zweck wird also das Interface Addressable eingeführt:

<?php 
	interface Addressable { 
		public function getAddress(); 
	} 

	class Address { 
		protected $streetName; 

		protected $streetNr; 

		protected $country; 

		public function __construct($streetName, $streetNr, $country='DE') { 
			$this->streetName = $streetName; 
			$this->streetNr = $streetNr; 
			$this->country = $country;	 
		}	 

		public function __toString() { 
			return $this->streetName.' '.$this->streetNr.' '.$this->country; 
		} 
	} 


	class Person implements Addressable{ 
		protected $firstName; 

		protected $lastName; 

		protected $address; 

		public function __construct($firstName, $lastName, Address $address) { 
			$this->firstName = $firstName; 
			$this->lastName = $lastName; 
			$this->address = $address; 
		} 

		/** 
		* @return Address 
		*/ 
		public function getAddress() { 
			return $this->address; 
		} 
	} 

	class Company implements Addressable { 
		protected $name; 

		protected $address; 

		public function __construct($name, Address $address){ 
			$this->name = $name; 
			$this->address = $address;	 
		} 

		/** 
		* @return Address 
		*/ 
		public function getAddress() { 
			return $this->address; 
		} 
	} 

	class RoutingService { 
		public function calculateRoute(Addressable $subject) { 
			echo 'Routing to '.$subject->getAddress(); 
		} 
	} 

	$aoe 	= new Company('AOE', new Address('Borsigstr.','3')); 
	$heinz 	= new Person('Heinz', 'Müller', new Address('Dorfstraße','47b')); 

	$routingService = new RoutingService(); 
	$routingService->calculateRoute($aoe); 
	$routingService->calculateRoute($heinz); 
?>


Das obere Beispiel definiert 4 Klassen und ein Interface:

  1. Das Interface "Addressable" wird verwendet um die Zusicherung zu garantieren, dass Klassen die es implementieren immer eine Adresse mit "getAddress()" liefern können.

  2. Die Klasse "Address" modeliert die Struktur der eigentlichen Adresse. Die Method __toString() wird hier implementiert um das Objekt mittels "echo" ausgeben zu können.

  3. Die Klasse "Person" implementiert das Interface "Addressable" indem es mit "implements" singnalisiert, dass diese Klasse ein bestimmtes Interface implementiert. Dadurch muss die Methode "getAddresss()" bereitgestellt werden und genau das ist auch der Fall. Eine Klasse kann beliebig viele Interfaces implementieren.

  4. Die Klasse "Company" implementiert das Interface "Addressable" ebenfalls.

  5. Der "RoutingService" ist dazu da eine Route zu einer Addresse zu berechnen und benötigt dazu ein "Addressable" Objekt. Obwohl die Klassen Person und Company direkt nichts miteinander zu tun haben, so haben sie doch gemeinsam, dass sie eine Adresse liefern können. Der Routing Service kann mit allem arbeiten, dass eine Adresse bereitstellen kann.

Navigation