PHP und OOP: Teil 2, Sichtbereiche (public, protected, private)

PHP Turtle


Teil 1: Aufbau einer Klasse


Das Beispiel

class Turtle {

  public $name;
  protected $age = 0;
  private $owner;

  public function __construct( $name ) {
    $this->name = $name;
    $this->owner = $owner;
  }

  public function haveBirthday() {
    $this->age++;
    $this->wearRibbon();
  }

  private function wearRibbon() {
    echo $this->name . ' wears now a yellow ribbon.' . "\n";
    $this->speak( 'That\'s awesome!' );
  }

  protected function speak( $say ) {
    echo $this->name . ' says: ' . $say . "\n";
  }


  //---------- Getter/Setter

  public function getAge() {
    return $this->age;
  }

  public function getOwner() {
    return $this->owner;
  }

  public function setOwner( $new_owner ) {
    $this->owner = $new_owner;
  }  

}

Die Schlüsselwörter für diesen Artikel sind public, protected und private. Sie stehen sowohl vor den Attributen als auch den Methoden.

Public

$my_turtle = new Turtle( 'Paul', 'Seba' );
$my_turtle->name = 'Le Foo';

Legen wir nun eine neue Schildkröte mit dem Namen „Paul“ an. Gleich in der nächsten Zeile ändern wir den Namen aber wieder. Da das Attribut $name als public definiert wurde, können wir es von außen abfragen und verändern.

Protected

$my_turtle->age = 40;

Versuchen wir das mal mit dem Alter. Das Ergebnis lautet:

PHP Fatal error: Cannot access protected property Turtle::$age

Genau wie gewünscht! Denn in das Alter einer Schildkröte soll nicht einfach so eingegriffen werden können. Am Geburtstag wird sie 1 Jahr älter – nur so und nicht anders.

//---------- Getter/Setter

public function getAge() {
  return $this->age;
}

public function getOwner() {
  return $this->owner;
}

public function setOwner( $new_owner ) {
  $this->owner = $new_owner;
}

Trotzdem möchte man das Alter ja abfragen können. Dafür hat es sich in jeder Programmier­sprache, die Klassen kennt, etabliert, Getter und Setter zu verwenden. Die Namens­konvention ist get/set + Attributname.

echo 'Turtle age: ' . $my_turtle->getAge() . "\n";

Lasst mich das noch einmal betonen: Gewöhnt euch Getter und Setter an!

Für Methoden, die protected sind, gilt das Gleiche wie für Attribute: Sie sind nur innerhalb der Klasse verwendbar.

Private und Vererbung

Innerhalb unserer Klasse ist private erst einmal gleichbedeutend mit protected – Alles ist nur innerhalb der Klasse sichtbar. Der Unterschied macht sich bei der Vererbung bemerkbar. Erstellen wir also eine Klasse, die von Turtle erbt.

class GiantTurtle extends Turtle {

  public function partyHard() {
    $this->speak( 'Let\'s party hard!' );
    $this->wearRibbon(); // Nope, that won't work!
  }

}

Schlüsselwort für das Erben von einer anderen Klasse ist extends. Die neue Klasse kennt alle Attribute und Methoden, die in ihrer Vaterklasse als public oder protected definiert wurden; einschließlich dem Konstruktor.

$giant_turtle = new GiantTurtle( 'Monka', 'Seba' );
$giant_turtle->partyHard();

Lassen wir unsere fehlerhafte Klasse nun mal in ihr Verderben rennen.

Monka says: Let's party hard!
PHP Fatal error: Call to private method Turtle::wearRibbon() from context 'GiantTurtle'

Alles was in Turtle als private definiert wurde, kann in GiantTurtle nicht mehr verwendet werden. „Aber, aber!“, höre ich da schon jemanden rufen. „Was ist denn mit haveBirthday() und dem $owner-Attribut?“

Der geerbte Konstruktor und die Methode haveBirthday() gehen weiterhin, denn ihre Implementierung findet noch in Turtle statt! Nur in GiantTurtle können wir das Attribut und die Methode nicht mehr explizit verwenden. Ja, etwas verwirrend.


Zum Mehrlesen

Wie geht es weiter?

Im 3. Teil zu OOP in PHP kommen die statischen Methoden dran.