2015-10-14 17 views
5

Chciałem utworzyć interfejs w PHP, ale nie chciałem, aby był zbyt restrykcyjny w kwestii typu argumentów, które zaakceptowałby w jednej z publicznych metod. Nie chciałem zrobićInterfejs PHP akceptuje argument interfejsu?

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

Bo nie chce przekazać go instancję myClass. Ale chcę mieć pewność, że obiekt przekazany spełnia pewne parametry, które mogłem osiągnąć poprzez zdefiniowanie interfejsu. Więc pomyślałem, aby określić klas, które wykorzystują interfejsy, tak jak poniżej:

<?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) {} 
} 

Ale pojawia się błąd PHP Fatal error: Declaration of obj::takes_a() must be compatible with iC::takes_a(iA $a) on line 15

Czy istnieje sposób upewnić się, że argument akceptuje tylko klasę pewnego interfejsu? A może nadwerężyłem/nad-inżynierię tego?

+0

kiedy zaimplementować interfejs, podpis metod musi być taka sama, jak w interfejsie. ('public function takes_a (iA $ a);' w twojej klasie obj), ale możesz przekazać jabłko na tym przykładzie. '$ o = new obj(); $ o-> takes_a (new apple()); ' –

+0

@ RaphaelMüller Nie rozumiem, co mówisz - wiem, jak przekazać obiekt Apple. Dodanie linii do końca skryptu nie powoduje jej kompilacji; nadal narzeka, że ​​podpis funkcji nie jest zgodny. – user151841

+4

patrz https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29. Przez zawężenie 'takes_a()', aby zezwolić tylko na "jabłko", uniemożliwiasz innym "iA", ale interfejs iC wymaga akceptacji _any_ iA jako parametru. – VolkerK

Odpowiedz

3

Twoja koncepcja jest całkowicie poprawna. Jest tylko jedna mała niewłaściwa część. Twoje metody klas muszą mieć ten sam podpis niż określony w interfejsie.

jak VolkerK powiedział:

zobaczyć wikipedia. Zawężając metodę takes_a(), aby zezwolić tylko na "jabłko", odrzucasz inne "iA", ale interfejs iC wymaga akceptacji dowolnego iA jako parametru. - VolkerK

Mając to na uwadze zobaczyć poprawiony kod:

<?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());