maximilius: Abstraktion

Gibt es bei PHP die Möglichkeit den Konstruktor einer Kindklasse aufzurufen aber die erzeugte Instanz als Typ der Elternklasse abzuspeichern?

Ich würde dies gerne zwecks Abstraktion so handhaben, dass wenn ich folgende Klassen habe...

Elternklasse: Auto
Kindklasse: Porsche

... eine Instanz von Porsche erzeuge, aber als Auto behandle.

Der Code in Java sähe so aus:
Auto meinAuto = new Porsche();

Ist das in PHP umsetzbar?
Wenn ja, wie?

lg Stephan

  1. echo $begrüßung;

    Gibt es bei PHP die Möglichkeit den Konstruktor einer Kindklasse aufzurufen aber die erzeugte Instanz als Typ der Elternklasse abzuspeichern?

    Nein. Auch nicht mit einem Typecast, weil der nur auf die Grundtypen anwendbar ist.

    Ich würde dies gerne zwecks Abstraktion so handhaben, dass wenn ich folgende Klassen habe...
    Elternklasse: Auto
    Kindklasse: Porsche
    ... eine Instanz von Porsche erzeuge, aber als Auto behandle.

    Der Code in Java sähe so aus:
    Auto meinAuto = new Porsche();

    Variablen sind in PHP nicht streng typisiert, weswegen du keinen bestimmten Typ erzwingen kannst. Wenn du den Porsche nur als Auto behandeln willst, dann tu einfach so, als ob er nur ein Auto wäre. Das schließt auch Abfragen mit instanceof und das Type Hinting mit ein.

    echo "$verabschiedung $name";

    1. Hallo,

      ich danke für eure beiden Antworten.
      Dann muss ich dokumentieren und kann es nicht erzwingen, dass nur die Methoden der (in meinem Fall abstrakten) Elternklasse benutzt werden sollen, damit in Hinblick auf die Wartbarkeit das Objekt der Kindklasse ausgetauscht werden kann.

      lg Stephan

      1. echo $begrüßung;

        Dann muss ich dokumentieren und kann es nicht erzwingen, dass nur die Methoden der (in meinem Fall abstrakten) Elternklasse benutzt werden sollen, damit in Hinblick auf die Wartbarkeit das Objekt der Kindklasse ausgetauscht werden kann.

        Wozu benötigst du dann eine Kindklasse?

        echo "$verabschiedung $name";

        1. Wozu benötigst du dann eine Kindklasse?

          Ich möchte die Webanwendung wartbar programmieren.
          Bleiben wir bei dem Beispiel Auto:

          $oAuto = new Porsche();  
          $oAuto->beschleunige();  
          $oAuto->verzoegere();  
          echo $oAuto->getZurueckgelegteStrecke();
          

          Es kann ja sein, dass irgendwann entschieden wird, dass der Porsche gegen einen Traecker ausgetauscht werden soll:

          $oAuto = new Traecker();  
          $oAuto->beschleunige();  
          $oAuto->verzoegere();  
          echo $oAuto->getZurueckgelegteStrecke();
          

          Jetzt hat sich nur eine Codezeile geändert, aber die Webanwendung funktioniert weiterhin, weil sie nur auf den abstrakten Methoden von Auto arbeitet.

          Es darf nicht passieren, dass im ersten Codeausschnitt eine Methode aufgerufen wird, die in Auto nicht vorhanden war aber mit der Erweiterung durch Porsche hinzukam.
          Dann kann ich das Objekt nicht mehr gegen eines einer anderen Kindklasse austauschen.

          lg Stephan

          1. echo $begrüßung;

            Es darf nicht passieren, dass im ersten Codeausschnitt eine Methode aufgerufen wird, die in Auto nicht vorhanden war aber mit der Erweiterung durch Porsche hinzukam.
            Dann kann ich das Objekt nicht mehr gegen eines einer anderen Kindklasse austauschen.

            Man kann mit PHP nicht verhindern, dass jemand was notiert, das nicht vorhanden ist. Es gibt ja keinen Kompilationsvorgang, der solche Fehler findet. Zudem gibt es magische Funktionalität, wie die __call()-Methode, die als Catch-All fungiert. Selbst bei Type Hinting auf die Elternklasse schützt dich nichts davor, etwas aufzurufen, dass nur in einer Kindklasse definiert ist. Für eine Elternklasse würde ja __call() einspringen können. Es liegt in der Verantwortung des Programmierers, solche Fehler zu vermeiden. Durch Type Hinting gibst du ja schon zu erkennen, dass eine Funktion/Methode sich auf die Verarbeitung der angegebenen Klasse beschränkt.

            echo "$verabschiedung $name";

            1. Man kann mit PHP nicht verhindern, dass jemand was notiert, das nicht vorhanden ist. Es gibt ja keinen Kompilationsvorgang, der solche Fehler findet. Zudem gibt es magische Funktionalität, wie die __call()-Methode, die als Catch-All fungiert. Selbst bei Type Hinting auf die Elternklasse schützt dich nichts davor, etwas aufzurufen, dass nur in einer Kindklasse definiert ist. Für eine Elternklasse würde ja __call() einspringen können. Es liegt in der Verantwortung des Programmierers, solche Fehler zu vermeiden. Durch Type Hinting gibst du ja schon zu erkennen, dass eine Funktion/Methode sich auf die Verarbeitung der angegebenen Klasse beschränkt.

              In Verbindung mit deinem anderen Beitrag ...

              PHP ist ja per se als Quellcode vorliegend

              ... hat in mir die Erkenntniss geweckt, dass PHP so ausgelegt ist, dass Programmierfehler nicht zwingend zum Absturz der Webanwendung führen sollen.
              Daher ist es so offen.

              Wie gesagt: Dann muss ich es eben gut dokumentieren.

              lg Stephan

      2. n'abend,

        Dann muss ich dokumentieren und kann es nicht erzwingen, dass nur die Methoden der (in meinem Fall abstrakten) Elternklasse benutzt werden sollen, damit in Hinblick auf die Wartbarkeit das Objekt der Kindklasse ausgetauscht werden kann.

        Das würde ich so nicht sagen. Erzwingen kann man so ziemlich vieles - auch wenn das oft weder elegant noch sinnvoll ist.

        Du könntest durchaus alle Methoden protected setzen (php != java; protected bedeutet in java, dass das ganze Package Zugriff hat, private nur die Klasse und Kindklassen. In PHP bedeutet private, dass nur die Klasse selbst Zugriff hat, sollen auch erbende Klassen das Privileg des Zugriffs haben, muss die Methode protected sein). In der Kindklasse hast du dann an sich nur noch Methoden, die von außen gar nicht aufrufbar sind. In der Elternklasse könntest du dann mittels __call() den Zugriff auf bestimmte Methoden erlauben. Auf diese Art und Weise könntest du den externen Zugriff auf weitere (protected!) Methoden der Kindkassen tatsächlich verwehren - mit welchem Sinn und Zweck auch immer...

        P.S.: Beim Suchen nach der richtigen Doku-Seite bin ich über __sleep(), __wakeup() und gestolpert, die ich zuvor nicht kannte. Da soll nochmal einer behaupten anderen Helfen wäre vertane Zeit...

        weiterhin schönen abend...

        --
        #selfhtml hat ein Forum?
        sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
        1. Du könntest durchaus alle Methoden protected setzen (php != java; protected bedeutet in java, dass das ganze Package Zugriff hat, private nur die Klasse und Kindklassen. In PHP bedeutet private, dass nur die Klasse selbst Zugriff hat, sollen auch erbende Klassen das Privileg des Zugriffs haben, muss die Methode protected sein). In der Kindklasse hast du dann an sich nur noch Methoden, die von außen gar nicht aufrufbar sind. In der Elternklasse könntest du dann mittels __call() den Zugriff auf bestimmte Methoden erlauben. Auf diese Art und Weise könntest du den externen Zugriff auf weitere (protected!) Methoden der Kindkassen tatsächlich verwehren - mit welchem Sinn und Zweck auch immer...

          Stimmt, das würde gehen.
          Ich würde die Anwendung gerne wartbar halten.
          Wegen der Wartbarkeit möchte ich ja erst die abstrakte Elternklasse verwenden.
          Aber zur Wartbarkeit gehört auch dazu, dass man den Code gut lesen und verstehen kann.
          Ich glaube, wenn ich die von dir beschriebene Vorgehensweise in den Code einbaue, muss man sich eine Weile reinfuchsen, bevor man versteht, was da eigentlich passiert, bzw. warum dieser Weg gegangen wurde.

          Was denkst du?

          lg Stephan

          1. echo $begrüßung;

            Ich glaube, wenn ich die von dir beschriebene Vorgehensweise in den Code einbaue, muss man sich eine Weile reinfuchsen, bevor man versteht, was da eigentlich passiert, bzw. warum dieser Weg gegangen wurde.
            Was denkst du?

            Ich bin zwar nicht globe, aber: KISS. Type Hinting und gut ist. Alles andere ist das Problem des Programmierers, der es versaut. Du kannst ja auch nicht verhindern, dass jemand die Einschränkung, die du vielleicht eingebaut hast, wieder entfernt. PHP ist ja per se als Quellcode vorliegend, wenn nicht irgendwelche Verschleierer eingesetzt werden. Aber dann besteht ja auch kein Problem mehr, weil es nicht änderbar ist.

            echo "$verabschiedung $name";

          2. n'abend,

            Was denkst du?

            ich würde das von mir beschriebene Verfahren nicht implementieren, wenn man mich dafür bezahlen würde. Ich habe die Möglichkeit lediglich aufgezeigt, damit man sehen kann, dass dein Wunsch eben doch umsetzbar ist - das ändert an der Natur des Wunsches jedoch herzlich wenig.

            Entweder du gewöhnst dich daran, dass PHP eben nicht $insertRandomProgrammingLanguage ist, oder du steigst auf $insertOtherLanguageWithOtherProblems um.

            weiterhin schönen abend...

            --
            #selfhtml hat ein Forum?
            sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
  2. n'abend,

    Gibt es bei PHP die Möglichkeit den Konstruktor einer Kindklasse aufzurufen aber die erzeugte Instanz als Typ der Elternklasse abzuspeichern?

    Ich würde dies gerne zwecks Abstraktion so handhaben, dass wenn ich folgende Klassen habe...

    Elternklasse: Auto
    Kindklasse: Porsche

    ... eine Instanz von Porsche erzeuge, aber als Auto behandle.

    Der Code in Java sähe so aus:
    Auto meinAuto = new Porsche();

    Java ist eine streng typisierte Sprache - PHP hingegen nicht. In Java musst du den Datentyp einer Variablen spezifizieren, damit der Compiler deinen Code entsprechend verarbeiten kann - in PHP musst du das nicht nur nicht, du kannst es erst gar nicht. Type Hinting setzt auf instanceof.

    weiterhin schönen abend...

    --
    #selfhtml hat ein Forum?
    sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|