• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

extends vs. wrapping ???

aichingm

Mitglied
hi,

ich hab folgendes Problem: Ich habe 2 Klassen Foo und Bar. Ich will mit Hilfe von Bar, Foo erweitern. Foo besitzt eine Methode namens xy mit 2 Parametern also xy($x, $y). In Bar möchte ich xy mit 2 Type hinted Parametern aufrufen also so xy(ObjectX $x, ObjectY $y). Wenn ich das:
PHP:
class Foo{
        public function xy(){
                return x*y;    
        }
}
class Bar extends Foo{
        private $x;

        public function xy(ObjectX $x, ObjectY $y){
                $this->x = $x;
                return x*y;     
        }
}
mache bekomme ich einen Fehler:
Code:
[COLOR=#000000][FONT=Times New Roman]Strict Standards: Declaration of Bar::xy() should be compatible with that of Foo::xy() in /bla/bla/bla/FooBar.php on line 1[/FONT][/COLOR]

Jetzt hab ich 2 Möglichkeiten erstens ich bleibe bei extends:

PHP:
class Foo{
        public function xy(){
                 return x*y;           
        }
}

class Bar extends Foo{
        public function xy_bla(ObjectX $x, ObjectY $y){
                 $this->x = $x;
                 parent::xy($x, $y);
        }
}

oder zweites ich wrape die Foo klasse:

PHP:
class Foo{
        public function xy(){
                 return x*y;    
        }
}
class Bar {
        private $foo
        
        public function __construct(){
               $foo = new Foo();
        }        
        public function xy_bla(ObjectX $x, ObjectY $y){
                $this->x = $x;
                return $foo->xy($x, $y);
        }
}
Ich würde gerne den Namen der Methode in der parent-Klasse behalten bzw. sie (die Methode) gerne überschreiben damit sie das selbe macht wie in der Doku von Foo nur eben mit einen kleinen Zusatz.

Wissen möchte ob es einen wesentlichen Nachteil bei der zweiten Lösung gibt oder ob es keine Unterschied macht?? Sollte es eine weiter Lösungen geben bin ich gerne für alles offen!


vielen Dank Mario!

PS: is_subclass_of() ist zu vernachlässigen bzw wird nicht zwingenderweise gebraucht.
 
Zuletzt bearbeitet:
Werbung:
Das scheint ein Designfehler zu sein. Mit Foo, Bars, X und Y kann man nichts anfangen. Worum geht es konkret?
 
haha jetzt hab ich mir extra Mühe gegeben das Problem so objektiv wie möglich darzustellen :mrgreen: aber gut hier mein konkreter Fall:

PHP:
class ZipFile extends ZipArchive{
   private $addedfileNum;
   public function __construct(){
      $this->addedfileNum = 0;   
   }       
   public function addFile(String $filename, String $loacalname = null){      
      $this->addedfileNum++;      
      parent::addFile($filename, $loacalname);
   }
}

der Fehler ist der selbe wie oben
Strict Standards: Declaration of ZipFile::addFile() should be compatible with that of ZipArchive::addFile() in /bla/bla/bla/ZipFile.php on line 1

mario

PS: die String klasse ist eine von mir geschriebene Klasse. (string != String)
 
Werbung:
Der Methodenrumpf muss der Selbe sein:

PHP:
class ZipArchive{  
   public function addFile(String $filename, String $loacalname = null){      
   }
}  

class ZipFile extends ZipArchive{  
   public function addFile(String $filename, String $loacalname = null){      
   }
}

Aber ich kann dein konkretes Beispiel nicht nachvollziehen.

Wo siehst Du den Unterschied zwischen einer ZIP-Datei und einem ZIP-Archiv? Ein ZIP-Archiv ist eine Datei, die durch das Zusammenfassen mehrerer Dateien ensteht. Überdenk nochmal deine Klassen.


Ich würde das z.B. so aufbauen:

PHP:
class File {
    private $name;
    private $extension;
    private $basePath;
    // ...
}

class Folder {
    private $name;
    private $basePath;
    // ...

    private $files = array();

    public function addFile(File $file) {
        $this->files = $file;
    }

    public function addFolder(Folder $folder) {
        $this->files = $folder;
    }
}

class ZipArchive extends File {
    private $files = array();

    public function addFile(File $file) {
        $this->files = $file;
    }

    public function addFolder(Folder $folder) {
        $this->files = $folder;
    }

    public function extract() {

    }

    public function create() {

    }
}
 
klar, dass du das nicht nach vollziehen kannst. Ich hab vergessen zu sagen das ZipArchive eine Php-Standard-Klasse ist. siehe:PHP: ZipArchive - Manual

Edit: sonst hätte ich eh den code dazu geschrieben, aber ich dachte es ist klar, dass wenn ich eine klasse verwende die ich nicht definiere, es eine "core-Klasse" ist. :D

@Asterixus wenn ich instanceof verwende verliere ich das type hinting was mir gar nicht gefallen würde!

mario
 
Werbung:
Zend Studio und Netbeans (möglicherweise auch PDT) reagieren auf instanceof mit implizitem Typehinting.

Du darfst einfach nicht die Signatur einer Methode ändern.
 
Das Problem ist einfach, dass sich ZipFile bei veränderter Signatur/„Verhaltenslogik“ dann nicht verhält wie ZipArchive. Wo ein ZipArchive erwartet wird, kann ich kein ZipFile übergeben. Das verletzt Grundregeln der Vererbung. So gesehen fällt das meines Erachtens raus.

Gemeint sind in der Signatur ja Strings (der primitive PHP-Datentyp). Der ist nur nicht typehintbar.

(Wobei das aufgrund der schwachen Typisierung eben auch nicht ganz richtig ist. Theoretisch ist alles, das auf String castbar ist, nach PHP-Logik in solchen Fällen ein String. Man muss solche Angaben wohl lesen als: primitiveDataTypeOrObjectWith__toStringMethod. Alles etwas unübersichtlich.)

Ich halte es generell für besser, ZipFile als Wrapper für ZipArchive anzulegen, also intern in ZipFile mit einer ZipArchive-Instanz zu arbeiten, aber explizit nicht von dieser zu erben.

PS: Klassennamen in PHP sind case-insensitive. Falls jemals (Pseudo-)Typehinting für primitive Datentypen kommt (das schwirrt seit langer langer Zeit durch die Community Scalar type hinting is harder than you think), fällst du mit einem Klassennamen „String“ (was ja „identisch“ ist zu „string“, weil PHP f(foo $f) auch für einen Typehint auf Foo hält) in irgendeiner Form möglicherweise (!) auf die Nase. Ich würde empfehlen, da einen abweichenden Namen wie CString oder TString o. ä. zu wählen. Die PHP-Leute achten zwar in der Regel sehr genau darauf, bei solchen Dingen die Abwärtskompatibilität und die Funktion bestehender Scripts nicht zu beeinflussen, aber – na ja – es ist an der Stelle einfach ein realistisches Risiko, dass die sich die Namen krallen.

Das ist glaube ich auch der Grund, warum die experimentellen SPL-Typehints ebenfalls ein Präfix haben. PHP: Installing/Configuring - Manual
 
Zuletzt bearbeitet:
Werbung:
also ZipFile als Wrapper für ZipArchive. Vielen Dank an mermshaus für die ausführliche Antwort!

Und auch für den
case-insensitive-Tipp. Ich werde mir was überlegen vielleicht einfach StringObj oder so was in der Art. Wo bei sich das möglicherweise auch über namespaces lösen lässt.

Viel lieber als type hinting für string, int usw. hätte ich gerne vernünftige Klassen statt den skalaren Datentypen, aber das liegt wohl nicht in der Natur von PHP^^. Die Problemlösung wäre php case-sensitive zu machen aber ich glaube bis das passiert dauert es noch, php serckt ja erst in den "Anfängen" der oop. Trotzdem wundert es mich das $a != $A ist aber a() == A(), wenn
case-sensitive dann doch bitte überall!

noch mal danke an euch alle! Mario
 
Zurück
Oben