2015-10-14 4 views
5

Ich wollte eine Schnittstelle in PHP machen, aber ich wollte nicht, dass es zu restriktiv ist, welchen Argumenttyp es in einer der öffentlichen Methoden akzeptieren würde. Ich wollte nichtPHP-Schnittstelle akzeptiert Schnittstellenargument?

interface myInterface { 
    public function a(myClass $a); 
} 

tun, weil ich es nicht eine Instanz von myClass passieren möge. Aber ich möchte sicherstellen, dass das übergebene Objekt bestimmten Parametern entspricht, die ich durch Definition einer Schnittstelle erreichen könnte. Also dachte ich, Klassen zu spezifizieren, die Schnittstellen verwenden, etwa so:

<?php 

interface iA {} 
interface iB {} 

interface iC { 
    public function takes_a(iA $a); 
    public function takes_b(iB $b); 
} 

class apple implements iA {} 
class bananna implements iB {} 

class obj implements iC { 
    public function takes_a(apple $a) {} 
    public function takes_b(bananna $b) {} 
} 

Aber, erhalte ich die Fehler PHP Fatal error: Declaration of obj::takes_a() must be compatible with iC::takes_a(iA $a) on line 15

Gibt es eine Möglichkeit sicherzustellen, dass ein Argument nur eine Klasse von einer bestimmten Schnittstelle akzeptiert? Oder übertreibe ich das?

+0

, wenn Sie Ihre Schnittstelle implementieren, die Signatur der Methoden, wie in der Schnittstelle gleich sein muss. ('public function takes_a (iA $ a);' in Ihrer obj-Klasse), aber Sie können Apple für diese Instanz übergeben. '$ o = neues obj(); $ o-> takes_a (neuer Apfel()); ' –

+0

@ RaphaelMüller Ich verstehe nicht, was Sie sagen-- Ich weiß, wie man ein Apple-Objekt übergeben. Wenn Sie Ihre Zeile am Ende des Skripts hinzufügen, wird sie nicht kompiliert. es beschwert sich immer noch über die nicht übereinstimmende Funktionssignatur. – user151841

+4

siehe https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29. Indem man 'takes_a()' so einschränkt, dass nur "Apple" erlaubt sind, verbieten Sie andere "iA" s, aber die Schnittstelle, die iC anfordert, _any_ iA als Parameter zu akzeptieren. – VolkerK

Antwort

3

Ihr Konzept ist völlig korrekt. Es gibt nur einen kleinen falschen Teil. Ihre Klassenmethoden müssen die gleiche Signatur aufweisen wie in Ihrer Schnittstelle angegeben.

als VolkerK sagte:

wikipedia sehen. Indem Sie takes_a() einschränken, um nur "Apple" zu erlauben, verbieten Sie andere "iA" s, aber die Schnittstelle, die iC verlangt, jedes iA als Parameter zu akzeptieren. - VolkerK

diesem Hintergrund sehen die korrigierte Code:

<?php 

interface iA { 
    function printtest(); 
} 
interface iB { 
    function play(); 
} 

//since an interface only have public methods you shouldn't use the verb public 
interface iC { 
    function takes_a(iA $a); 
    function takes_b(iB $b); 
} 

class apple implements iA { 
    public function printtest() 
    { 
     echo "print apple"; 
    } 
} 
class bananna implements iB { 
    public function play() 
    { 
     echo "play banana"; 
    } 
} 

//the signatures of the functions which implement your interface must be the same as specified in your interface 
class obj implements iC { 
    public function takes_a(iA $a) { 
     $a->printtest(); 
    } 
    public function takes_b(iB $b) { 
     $b->play(); 
    } 
} 

$o = new obj(); 

$o->takes_a(new apple()); 
$o->takes_b(new bananna());