[Tutorial] Einblick in die OoP - Teil 2

  • Moin moin.

    Hiermit veröffentliche ich mal den zweiten Teil über die Objektorientierte Programmierung in PHP.
    In diesem Beitrag wollen wir uns mit Vererbung von Objekten beschäftigen.
    Ihr solltet diesen Beitrag gelesen haben - habt ihr das nicht getan, dann solltet ihr den ersten Teil zuerst lesen und verstehen.

    Inhalt
    1. Grundlegendes
    1.1 Der Unterschied zwischen private und protected
    1.2 Das Schlüsselwort "final"
    1.3 Objekte Klonen
    2. Die Vererbung
    2.1 Methoden vererben
    2.2 Nachtrag zum Variablenzugriff
    3 Vor- und Nachteile von Vererbung

    1. Grundlegendes

    Wichtig bei Vererbung ist, dass man durch die objektorientierte Vererbung KEINE Werte direkt vererben kann, sondern nur Variablen und/oder Funktionen.

    1.1 Der Unterschied zwischen private und protected

    Eine Methode oder ein Attribut die als private deklariert ist, darf nur innerhalb der Klasse genutzt werden. Eine Veränderung eines Attributes oder Aufrufen einer Methode von außen ist nicht möglich. Man kann einer Methode auch private voran stellen (z.B. private getName() { ... } ), dann ist der Zugriff außerhalb des Objektes nicht möglich.
    Wenn jetzt also sogenannte "Kindklassen" Variablen und/oder Methoden erben sollen, müssen diese mit dem Schlüsselwort "protected" markiert werden.

    1.2 Das Schlüsselwort final

    Das Schlüsselwort "final" ist dafür gut, um Kindklassen davon abzuhalten, Methoden der Elternklasse zu überschreiben. Dazu stellt man der Definition einfach "final" (in der Elternklasse, nicht in der Kindklasse!) voran. Wird eine Klasse als final definiert, kann sie nicht erweitert werden.

    1.3 Objekte Klonen

    Hier gehe ich kurz darauf ein, dass man erzeugte Objekte auch einfach klonen kann.
    Nehmen wir an Dieters Fiffi namens Waldi hat das Zeitliche gesegnet. Und weil der die Frauen wie ein Magnet anzog, hat Dieter den Wuffi mal schnell geklont. Dies geschieht mit dem Schlüsselwort "clone".

    PHP
    $waldi = new Hund();
    $klon  = clone $waldi;

    2. Die Vererbung

    Die eigentliche Vererbung fängt schon beim Klassennamen an. Hier muss man das Schlüsselwort "extends" (zu Deutsch: hängt ab von / wird abgeleitet von) und die Klasse angeben, wovon man die Klasse abhängig macht.
    Außerdem gibt es noch das Schlüsselwort "parent", womit die Vererbung von Methoden passiert.

    2.1 Methoden vererben

    Als Vorwort hierzu stellen wir uns Autos vor. Man könnte jetzt für jede Automarke (wir nehmen hier als Beispiel Audi, Mercedes und Opel) eine eigene Klasse machen. Hier wird man aber schnell merken, dass es nicht so viel Sinn macht, jede set- und get-Methode 3 mal zu schreiben - abgesehen von den Variablen, die mehrfach deklariert werden müssen. Hier kommt das Thema Vererbung ins Spiel.
    Wir bauen uns eine Klasse, das "Grundgerüst" und leiten andere Klassen dann davon ab.

    Ich habe hier die Klasse "auto" als das Grundgerüst geschrieben. Man hat 4 Räder, Geschwindigkeit ist standard 0 und dann sind dort noch die Funktionen setSpeed und getSpeed.

    Wie man hier sehen kann, gibt es eine Klasse namens "auto", die im Zusammenhang mit dem Schlüsselwort "extends" steht.
    Da wir uns jetzt eben nicht die Arbeit machen wollen, den ganzen source code zu kopieren und alles 3 mal zu haben, sagen wir den Klasse "audi", "mercedes" und "opel" einfach "extends auto" - "audi extends auto" also: audi wird abgeleitet von auto.
    Wenn die Kindklasse keinen Konstruktor hat, wird automatisch der der Elternklasse ausgeführt. Ansonsten muss man diesen explizit verwenden.

    Jetzt haben wir also 3 Automarken erzeugt, die 150, 200 und 180 PS haben, 4 Räder haben und alle die Methoden setSpeed und getSpeed verwenden können, ohne, dass diese in jeder Klasse vorhanden sind.


    Mit dem Schlüsselwort "parent" kann man auf Methoden der Elternklasse zugreifen.
    Was ist aber, wenn die Elternklasse gar nicht die Methode hat, die man haben möchte - sondern nur die Großelternklasse diese besitzt? Dafür benutzt man anstatt

    PHP
    parent::methodenName(argumente)

    einfach

    PHP
    nameDerKlasseImVererbungskontext::methodenName(argumente)

    Man könnte also in diesem Falle anstatt "parent" auch einfach "auto" verwenden - dies hätte zwar den gleichen Effekt, ist aber nicht korrekt, da wir uns außerhalb des eigentlichen Objektkontextes bewegen.

    Hierzu nochmal ein besseres Beispiel:

    Eine simple Rechnung: Wir machen uns ein Rechteck und ein Quadrat, was von "Viereck" abgeleitet wird.
    Für die Klasse Rechteck werden einfach die Elternfunktionen aufgerufen.
    Bei der Klasse "Quadrat" habe ich es allerdings zum Verständnis etwas anders gemacht:

    PHP
    class quadrat extends viereck {
      protected $a = 2;
      protected $b = 2;
    
    
      public function calcUmfang() {
        $umfang = parent::calcUmfang();
        return $umfang.'<br />'.$this->a*$this->a;
      }
    }

    Da ich dieses mal beide Sachen in einer Funktion berechnen will und den Quellcode von "viereck" nicht kopieren will, überschreibe ich die Funktion calcUmfang().
    Damit ihr seht, wie das mit der Vererbung funktioniert, habe ich das Schlüsselwort "parent" mit eingebaut.
    Man greift mit "parent::calcUmfang()" auf die Methode "calcUmfang" der Elternklasse (hier "viereck") zu. Somit wird die Funktion calcUmfang der Elternklasse ausgeführt und man kann in dieser Klasse die Methode calcUmfang erweitern (hat keinen Einfluss auf andere Klassen, die neu von "viereck" abgeleitet werden). Damit die Fläche berechnet wird, kommt noch das return Statement hinzu. Es wird also Umfang (vorher berechnet und gespeichert) und danach die Fläche ausgegeben.

    2.2 Nachtrag zum Variablenzugriff
    Als Nachtrag zum Variablenzugriff möchte ich hier noch etwas anbringen.
    Hier ist die Klasse "auto" etwas erweitert:

    Jetzt hat jedes Auto standardmäßig 5 Sitze. Da mein Opel aber ein Familienwagen ist, der 8 Sitze hat, hat man in der Vererbung auch die Möglichkeit, Variablen zu überladen. Das geschieht dann so:

    PHP
    class opel extends auto {
      protected $engine = "180 PS";
      protected $seatCount = 8;
    }

    Wichtig dabei ist aber, dass dies nur $seatCount von Opel überschreibt und nicht von der Elternklasse "auto". Nur der Opel hat 8 Sitze.
    Objekte, die davor erzeugt wurden und danach erzeugt werden, haben wieder 5 Sitze (wegen des Grundgerüsts).

    3 Vor- und Nachteile von Vererbung
    Vorteile
    -Wiederverwendbarkeit
    -Keine Duplizierung von Quellcode mehr nötig
    -Fehlerkorrekturen einer Oberklasse wirken sich direkt und ohne Nacharbeiten auf die Unterklassen aus.

    Nachteile
    -Änderungen an der Wurzel einer Vererbungshierarchie beeinflussen alle erbenden Klassen - im schlimmsten Fall bewirkt eine Methode dann etwas ganz anderes
    -In Java können Speicherleaks durch Subobjekte entstehen, wenn diese nicht richtig freigegeben werden


    Das wars soweit von meiner Seite.
    Verbesserungsvorschläge, Fehlermeldungen und Feedback ist gern gesehen :-)

    Credits:
    -Schreiben des Tuts: 95% Leecher
    -Fürs anlesen diverser Dinge: 5% php.net

    ~Leecher

  • Zitat

    -Eine Unterklasse kann nicht auf Werte einer Oberklasse zugreifen


    Wie kommst du denn da drauf?

    Code
    php > class Blubb { protected $a = 'Hello World'; }
    php > class Blobb extends Blubb { public function Blobb() { echo $this->a; }}
    php > new Blobb();
    Hello World

    Generell machen sämtliche Beispiele keinen Sinn. Du überschreibst Attribute (ich wusste noch gar nicht, dass das geht *g*) ... Du überschreibst Methoden, nur um in ihr die überschriebene Methode mit den genau gleichen Parametern aufzurufen.

    Folgendes Beispiel ...


    ... hätte in dieser Form genau den gleichen Effekt ...

    Code
    class mann extends mensch {
      function getName() {
        return $this->name;
      }
    }


    (Denn der Rest ist in der Klasse mensch() schon vorhanden. Da mann diese, wie du selber schon sagst, erweitert, sind sämtliche Methoden und Attribute natürlich auch bei ihr vorhanden (denn sie sind ja als protected bzw. public deklariert))

    Ich bezweifle irgendwie, dass du das Thema selber verstanden hast ...

    (und auch ansonsten deckt das Tutorial das Thema nur rudimentär ab ...)

  • Das scheint wohl doch alles ein bisschen lange her zu sein, dass ich das mal gemacht habe ...

    Wenn ich deine Anmerkungen so lese, fällt mir direkt wieder ein, was da schief gelaufen ist - danke dafür! Ich habe da die Reihenfolge beim Vereben völlig verdreht.

    So, Beitrag ist nachbearbeitet.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!