Static & more

Muss man jetzt auch noch Architektur studieren, um objektorientiert programmieren zu können? Nein, muss man nicht :)

Bis jetzt haben wir immer nur "einfache" Klassen mit "einfachen" Methoden oder Eigenschaften benutzt. Einfach, das heißt, wir haben unser Objekt mit new erzeugt und mit dem -> auf Methoden oder Eigenschaften zugegriffen. Aber, es geht auch anders. Hier kommt jetzt wieder der doppelte Doppelpunkt ins Spiel :)

class BallKlasse {
	public static $farbe;
	
	public static function anmalen($farbe) {
		self::$farbe = $farbe;
	}
}

BallKlasse::anmalen("weiss");
echo BallKlasse::$farbe;

Man kann gut sehen, dass sich folgende Dinge geändert haben:

  • Die Eigenschaft und die Methode sind als static deklariert worden
  • das Objekt wird nicht mit new BallKlasse erzeugt, sondern es wird darauf mit Klasse::Methode zugegriffen
  • genauso wie auf die Methode, wird auch auf die Eigenschaft mit einem Klasse::$Eigenschaft zugegriffen
  • innerhalb der Klasse wird nicht mit $this-> gearbeitet

Tja, warum macht man sowas? Generell gilt, statische Methoden und Eigenschaften bewegen sich außerhalb des Objektkontextes. Das heißt, dass man nicht über ein erzeugtes Objekt darauf zugreift, sondern über den Klassennamen::Methodennamen. Ich persönlich benutzte statische Methoden zumeist in Datenbank-Klassen, im Singleton oder wenn ich mir "Zugriffsbäume" in Frameworks baue. Naja, ist wohl Geschmackssache.

Schnittstellen

Schnittstellen, wozu braucht an die denn? Naja, ganz einfach. Bis jetzt haben wir, wenn wir eine Klasse aus einer anderen Klasse mittels extends abgeleitet haben, Methoden aus der Elternklasse genutzt - oder eben nicht.

Stellen wir uns aber mal vor, ein Programmierer entwirft eine Elternklasse für das Bauen eines Hauses. Dann sollte diese Haus-Elternklasse zumindest über Methoden für Räume, Fenster u.s.w. verfügen, weil eben das alles ein Haus erst ausmacht. Und man könnte doch gleich die Elterklasse auch noch so schreiben, dass man, wenn man von ihr ableitet, unbedingt diese Methoden verwenden muss. Tja, genau das ist ein Interface. Alle Methoden, die man in einem Interface deklariert, müssen von den Kind-Klassen implementiert werden.

interface BallKlasse {
	
	public function anmalen($farbe);
	
	public function aufpumpen($luftmenge);
	
	public function beschreibe();
}

interface Shop {

	public function preisaendern();
}

class Ball implements BallKlasse, Shop {

	public $farbe;
	public $groesse;
	protected $preis;
	
	public function anmalen($farbe) {
		$this->farbe = $farbe;
	}
	
	public function aufpumpen($luftmenge) {
		$this->groesse = $luftmenge;
	}
	
	public function beschreibe () {
		$beschreibung = "Die Farbe ist ".$this->farbe."\n";
		$beschreibung .= "Die Groesse ist ".$this->groesse."\n";
		$beschreibung .= "Der Preis ist ".$this->preis."\n";
		return $beschreibung;
	}
	
	public function preisaendern() {
		$this->preis++;
	}
}
*

$ball = new Ball();
$ball->preisaendern();
$ball->preisaendern();
$ball->anmalen("weiss");
$ball->aufpumpen(1);
echo $ball->beschreibe();
//	Die Farbe ist weiss
//	Die Groesse ist 1
//	Der Preis ist 2

Abstrakt

Abstrakte Klassen sind, wie ich finde, eher eine Erweiterung von Interfaces. Während bei Interfaces eher ein rigider Ton vorherrscht, sieht das Ganze bei abstrakten Klassen doch eher demokratisch aus. Wenn wir von einer abstrakten Klasse ableiten, dann müssen wir zwar die vorgegebenen Methoden verwenden, können jedoch noch zusätzlich eigene Methoden dazuschreiben. Außerdem können wir die Sichtbarkeitsstufe der Methode für protected und public ändern. 

abstract class BallKlasse {
	
	protected abstract function anmalen($farbe);
	
	protected abstract function aufpumpen($luftmenge);
	
	protected abstract function beschreibe();
}

class Ball extends BallKlasse {

	public $farbe;
	public $groesse;
	protected $preis;
	
	public function anmalen($farbe) {
		$this->farbe = $farbe;
	}
	
	public function aufpumpen($luftmenge) {
		$this->groesse = $luftmenge;
	}
	
	public function beschreibe () {
		$beschreibung = "Die Farbe ist ".$this->farbe."\n";
		$beschreibung .= "Die Groesse ist ".$this->groesse."\n";
		$beschreibung .= "Der Preis ist ".$this->preis."\n";
		return $beschreibung;
	}
	
	public function preisaendern() {
		$this->preis++;
	}
}
	

$ball = new Ball();
$ball->preisaendern();
$ball->preisaendern();
$ball->anmalen("weiss");
$ball->aufpumpen(1);
echo $ball->beschreibe();
//	Die Farbe ist weiss
//	Die Groesse ist 1
//	Der Preis ist 2

Final

Ja, Final bedeutet genau das, wonach es aussieht. :) Eine mit final deklarierte Klasse kann man nicht ableiten - man kann nur ganz normal von ihr Objekte erzeugen. Wenn innerhalb einer normalen Klasse eine Methode als final gekennzeichnet ist, kann man zwar die Klasse ableiten, aber nicht mehr die Methode verwenden.

final class BallKlasse {
	
	public function anmalen($farbe) {}
	
	public function aufpumpen($luftmenge) {}
	
}

$klasse = new BallKlasse;
// Ja, das funktioniert :)
final class BallKlasse {
	
	public function anmalen($farbe) {}
}

class Ball extends BallKlasse {

	public $farbe;
	
	public function anmalen($farbe) {
		$this->farbe = $farbe;
	}
}
	

$ball = new Ball();
// <b>Fatal error</b>:  Class Ball may not inherit from final class (BallKlasse) 
class BallKlasse {
	
	public function anmalen($farbe) {}
	
	final public function aufpumpen($luftmenge) {}
	
}

class Ball extends BallKlasse {

	public $farbe;
	public $groesse;
	protected $preis;
	
	public function anmalen($farbe) {
		$this->farbe = $farbe;
	}
	
	public function aufpumpen($luftmenge) {
		$this->groesse = $luftmenge;
	}	
}


$ball = new Ball();
$ball->anmalen("weiss");
$ball->aufpumpen(1);
// <b>Fatal error</b>:  Cannot override final method BallKlasse::aufpumpen()