Eddie: Wie zwinge ich eine Unterklasse zum Setzen einer Variablen?

Hallo allerseits,

wie stelle ich am besten sicher, dass eine Unterklasse eine Variable setzt, die in der (abstrakten) Oberklasse noch als 'null' initialisiert wird?

Also: kann ich die Unterklasse irgendwie zwingen, die Variable setzen zu müssen? Wenn ich es vergesse, hätte ich gerne einen PHP-Fehler, ohne selbst auf die Existenz der Variable prüfen zu müssen :-)

Danke für eure Hilfe,
Eddie

--
Old men and far travelers may lie with authority.
  1. Hi

    ja klar, du kannst die Variable ja im Konstruktor verlangen. Wenn sie dann nicht mitgegeben wird gibts halt nen Fehler ;)

    Gruß
    Moe

    1. Hallo Moe,

      ja klar, du kannst die Variable ja im Konstruktor verlangen. Wenn sie dann nicht mitgegeben wird gibts halt nen Fehler ;)

      Vielleicht haette ich es noch ausführlicher darstellen sollen: die Variable soll private sein und nach aussen nicht sichtbar.

      Konkret geht es um eine abstrakte Suchklasse, und die Variable kann wahlweise den Wert "DB-Suche" oder "Dateisuche" haben - abhängig davon wird dann der Suchbegriff 'escaped', um kein Sicherheitsloch darzustellen.
      Sprich meine Unterklasse "SearchWhateverInDB" soll diese Variable setzen (setzen müssen!!!), abhängig davon geschieht das Escaping in einer entsprechenden Methode der abstrakten Parent-Klasse.

      Eddie

      --
      Old men and far travelers may lie with authority.
      1. echo $begrüßung;

        Konkret geht es um eine abstrakte Suchklasse, und die Variable kann wahlweise den Wert "DB-Suche" oder "Dateisuche" haben - abhängig davon wird dann der Suchbegriff 'escaped', um kein Sicherheitsloch darzustellen.
        Sprich meine Unterklasse "SearchWhateverInDB" soll diese Variable setzen (setzen müssen!!!), abhängig davon geschieht das Escaping in einer entsprechenden Methode der abstrakten Parent-Klasse.

        Vermutlich würde ich das eher so lösen, dass die Basisklasse eine Methode searchInDatabase() und eine searchInFile() anbietet. Abgeleitete Klassen können sich dann aussuchen, welche von beiden Methoden sie aufrufen möchten.
        Vielleicht ist es auch besser, eine abstrakte[*] Basisklasse zur generellen Suche zu erstellen, darauf spezialisiertere Klassen zu setzen, die dann vom Endanwender geerbt werden können.

        [*] im allgemeinen Wortsinn, nicht im Sinn des Attributs abstract

        echo "$verabschiedung $name";

        1. Hallo dedlfix,

          Vielleicht ist es auch besser, eine abstrakte[*] Basisklasse zur generellen Suche zu erstellen, darauf spezialisiertere Klassen zu setzen, die dann vom Endanwender geerbt werden können.

          Genau so soll's sein! Die eigentlichen Suchen unterscheiden sich sehr, teilweise mit verschiedenen Parametern, Zielen, Ausgabetypen. Darum legt die abstrakte Klasse eigentlich nicht viel mehr vor als einen Grundkonstruktor, ein paar Konstanten und die immer vorhandenen Methoden (queryDB, getOutput, ...)

          Eddie

          --
          Old men and far travelers may lie with authority.
          1. Moin!

            Genau so soll's sein! Die eigentlichen Suchen unterscheiden sich sehr, teilweise mit verschiedenen Parametern, Zielen, Ausgabetypen. Darum legt die abstrakte Klasse eigentlich nicht viel mehr vor als einen Grundkonstruktor, ein paar Konstanten und die immer vorhandenen Methoden (queryDB, getOutput, ...)

            Factory-Pattern?

            - Sven Rautenberg

            --
            "Love your nation - respect the others."
    2. echo $begrüßung;

      ja klar, du kannst die Variable ja im Konstruktor verlangen. Wenn sie dann nicht mitgegeben wird gibts halt nen Fehler ;)

      Eine Unterklasse muss den Konstruktor der Oberklasse nicht aufrufen. Es gibt dabei auch keinen Fehler. Mit dem Konstruktor der Oberklasse ist der Inhalt der Eigenschaft nicht sicherzustellen.

      Vielleicht hilft etwas Magie (von PHP5 ausgehend). Die Oberklasse definiert die Methode __get(). Diese Methode wird von PHP immer dann aufgerufen, wenn eine Eigenschaft nicht existiert. Gibt es die Eigenschaft, wird __get() nicht aufgerufen. Gibt es sie nicht, kann nun wie gewünscht reagiert werden.

      echo "$verabschiedung $name";

      1. Hallo dedlfix,

        Vielleicht hilft etwas Magie (von PHP5 ausgehend). Die Oberklasse definiert die Methode __get(). Diese Methode wird von PHP immer dann aufgerufen, wenn eine Eigenschaft nicht existiert. Gibt es die Eigenschaft, wird __get() nicht aufgerufen. Gibt es sie nicht, kann nun wie gewünscht reagiert werden.

        Super, ich glaub, das ist genau das, was ich brauche! :-)

        Danke!
        Eddie

        --
        Old men and far travelers may lie with authority.
  2. Hallo Eddie,

    wie stelle ich am besten sicher, dass eine Unterklasse eine Variable setzt, die in der (abstrakten) Oberklasse noch als 'null' initialisiert wird?

    muss es eine Variable sein? Ich würde eine abstrakte Methode in der Oberklasse definieren, die den Wert (Deine Variable oder was auch immer) zurückgibt. Diese Methode muss in einer konkreten Klasse definiert sein und kann dann benutzt werden, den Wert zurückzugeben.

      
    abstract class Fee {  
        abstract public function getVar();  
    }  
      
    class Feefee extends Fee {  
        public function getVar() {  
            return "whatever";  
        }  
    }  
    
    

    Gruß
    Olaf

    1. Hallo Olaf,

      muss es eine Variable sein?

      Nein, darf auch eine Konstante sein.

      Ich würde eine abstrakte Methode in der Oberklasse definieren, die den Wert (Deine Variable oder was auch immer) zurückgibt. Diese Methode muss in einer konkreten Klasse definiert sein und kann dann benutzt werden, den Wert zurückzugeben.

      So habe ich es auch erst versucht, Problem dabei: abstract-Methoden müssen public sein (keine Ahnung, warum) :-(
      Aber ich haette diese Einstellung eigentlich gern komplett verborgen!

      In meiner Antwort auf Moes Posting habe ich gerade auch nochmal was dazu geschrieben.

      Eddie

      --
      Old men and far travelers may lie with authority.
      1. echo $begrüßung;

        Problem dabei: abstract-Methoden müssen public sein (keine Ahnung, warum) :-(

        Es reicht, wenn diese protected sind. private ist nicht zulässig, weil sie dann ja nicht von der erbenden Klasse überschreiben werden kann.

        echo "$verabschiedung $name";

        1. Hallo dedlfix,

          Problem dabei: abstract-Methoden müssen public sein (keine Ahnung, warum) :-(

          Es reicht, wenn diese protected sind. private ist nicht zulässig, weil sie dann ja nicht von der erbenden Klasse überschreiben werden kann.

          Cool, verstanden! :-)
          Achso, dann ist es also nicht ganz so wie bei Java, da gilt ja soweit ich mich erinnere

          • private für die gesamte Vererbungshierarchie,
          • protected für's gesamte package (was es ja bei PHP nicht gibt)
          • und private für alle
            Oder?

          Eddie

          --
          Old men and far travelers may lie with authority.
          1. echo $begrüßung;

            Achso, dann ist es also nicht ganz so wie bei Java, da gilt ja soweit ich mich erinnere

            • private für die gesamte Vererbungshierarchie,

            private ist auch in Java auf die Klasse begrenzt.
            PHP kennt keine Packages, deswegen beschränkt protected den Zugriff auf die Klasse und alle erbenden Klassen, in Java zusätzlich darf zusätzlich noch das die Klasse enthaltende Package zugreifen.
            Außerdem kennt Java noch das Weglassen des Modifizierers, dann ist der Zugriff auf das Package beschränkt. In PHP ist das Weglassen jedoch wie eine public-Deklaration. (Das hat historische Gründe, denn unter PHP4 gab es keine Zugriffsmodifizierer, da war alles public.)

            echo "$verabschiedung $name";

      2. Hallo Eddie,

        […] So habe ich es auch erst versucht, Problem dabei: abstract-Methoden müssen public sein (keine Ahnung, warum) :-(

        Abstrakte Methoden können auch protected sein, nur private geht nicht (was allerdings auch ziemlicher Nonsens wäre)

        Mir ist noch nicht ganz klar, wofür Du überhaupt Deine Variable brauchst? Warum nicht so?

          
        abstract class AbstractSearch {  
            abstract protected function escape();  
        }  
          
        class FileSearch extends AbstractSearch {  
            protected function escape() {  
                // escape  
            }  
        }  
          
        class FileSearch extends DbSearch {  
            protected function escape() {  
                // escape  
            }  
        }  
        
        

        Gruß
        Olaf

        1. Hallo Olaf,

          Mir ist noch nicht ganz klar, wofür Du überhaupt Deine Variable brauchst?

          Weil das Escaping wiederum im Konstruktur der abstrakten Superklasse ablaeuft, abhängig vom Inhalt der Variablen.

          Konkret:

            
          abstract class Search  
          {  
              const SEARCHTYPE_DB = 1;  
              const SEARCHTYPE_FILESYSTEM = 2;  
            
              protected $int_searchType = null;  
            
              public function __construct($str_searchString)  
              {  
                  if (!in_array($this->int_searchType, array(self::SEARCHTYPE_DB, self::SEARCHTYPE_FILESYSTEM)))  
                  {  
                      // nicht gesetzt  
                      throw new Exception();  
                  }  
            
                  if ($this->int_searchType == self::SEARCHTYPE_DB)  
                  {  
                      // TODO:  
                      $str_searchString = addslashes($str_searchString);  
                  }  
                  else if ($this->getSearchType() == self::SEARCHTYPE_FILESYSTEM)  
                  {  
                      // TODO:  
                      $str_searchString = escapeshellarg($str_searchString);  
                  }  
            
                  $this->str_searchString = $str_searchString;  
              }
          

          Eddie

          --
          Old men and far travelers may lie with authority.
          1. Hallo Eddie,

            ich finde diese Lösung nicht so ideal.

            Deine abstrakte Klasse Search macht die ganze Arbeit alleine und implementiert schon zwei verschiedene konkrete Escapingalgorithmen, anstatt wirklich zu abstrahieren.

            Wenn Deine Klasse so aussieht, was ist an Search überhaupt abstrakt und wofür brauchst Du dann überhaupt noch abgeleitete konkrete Klassen?

            Ich würde eher so denken:

            Die abstrakte Klasse definiert, _was_ getan werden muss (Escapen – wie ist egal)

            Die konkreten Klassen definieren, _wie_ das getan werden muss.

            Wie Sven vorgeschlagen hat, könnte eine Factory/Fabrik die Erzeugung konkreter Objekte übernehmen und entscheiden, ob ein DBSearch- oder ein FileSearchobjekt zurück gegeben wird.

              
            $search = SearchFactory::getInstance($param1, $param2, $param3);  
            
            

            Gruß
            Olaf

            1. Hallo Olaf, (und hallo Sven!)

              Wie Sven vorgeschlagen hat, könnte eine Factory/Fabrik die Erzeugung konkreter Objekte übernehmen und entscheiden, ob ein DBSearch- oder ein FileSearchobjekt zurück gegeben wird.

              Ok, so hab ich's jetzt gemacht! Gleich viel besser :-)

              Danke für eure Hilfe,
              Eddie

              --
              Old men and far travelers may lie with authority.