Private Eigenschaften in PHP sind nur bedingt privat

05.03.2011

In PHP gibt es die Sichtbarkeiten public, protected und private. Diese stehen für öffentlich, geschützt und privat. In diesem Beitrag geht es um Letzteres.

Ein Beispiel für eine private Eigenschaft einer Klasse:

class Foo{
  private $x;}

$foo=new Foo();
$x=$foo->x; // Error

Auf die private Eigenschaft kann also von außerhalb des Objektes nicht zugegriffen werden. Oder doch? Hier ein weiteres Beispiel:

class Foo{
  private $x;

  public function setOthersX(Foo $foo, $x){
    $foo->x=$x;}}

$harmlessFoo=new Foo();
$evilFoo=new Foo();
$evilFoo->setOthersX($harmlessFoo, 23); // Works!

Das funktioniert, weil private nicht auf das Objekt, sondern auf die Klasse wirkt. Andere Objekte haben also sehr wohl Zugriff, wenn sie der gleichen Klasse angehören.

Unangenehm, denn eigentlich sollten die „Innereien“ eines Objekts von außen gar nicht sichtbar sein. Dass der Zugreifende der gleichen Klasse angehört, sollte da keinen Unterschied machen.

Aber es kommt noch schlimmer. Ein weiteres Beispiel:

class Foo{
  private $x;

  public function setOthersX(Foo $foo, $x){
    $foo->x=$x;}}

class FooChild extends Foo{
  public function getX(){
    return $this->x;}}

$offender=new Foo();
$victim=new FooChild();

$offender->setOthersX($victim, 42); // Works!
$x=$victim->getX(); // Ooops, is NULL!

Da die private Eigenschaft von Foo definiert wurde, wird sie auch Foo zugerechnet. Die Situation ist nun besonders absurd, denn in FooChild definierte Methoden haben keinen Zugriff auf $x, obwohl sie dem gleichen Objekt, also $victim, zugehörig sind, aber $offender, ein gänzlich anderes Objekt einer anderen Klasse (zugegebenermaßen gehört es der Elternklasse an), hat Zugriff.

Leider haben viele klassenbasierte Programmiersprachen die gleiche Macke.

Meines Erachtens ein äußerst unbefriedigender Zustand. Besser gelöst ist das in JavaScript, wo das Äquivalent zu privaten Eigenschaften, Closures, objektgebunden ist. Durch den gleichen Konstruktor erzeugte Objekte können sich diesbezüglich nicht gegenseitig ins Handwerk pfuschen.