Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP interface accepts interface argument?

Tags:

oop

php

I wanted to make an interface in PHP, but I didn't want it to be too restrictive on what argument type it would accept in one of the public methods. I didn't want to do

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

Because I may not want to pass it an instance of myClass. But, I do want to make sure that the object passed conforms to certain parameters, which I could accomplish by defining an interface. So I thought to specify classes that use interfaces, like 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 ) {}
}

But, I get the error PHP Fatal error: Declaration of obj::takes_a() must be compatible with iC::takes_a(iA $a) on line 15

Is there a way ensure that an argument accepts only a class of a certain interface? Or perhaps am I overthinking/over-engineering this?

like image 412
user151841 Avatar asked Oct 20 '22 00:10

user151841


1 Answers

Your concept is totally correct. There is only one little wrong part. Your classes methods must have the same signature than specified in your interface.

as VolkerK said:

see wikipedia. By narrowing down takes_a() to only allow "apple"s you disallow other "iA"s, but the interface iC demands to accept any iA as a parameter. – VolkerK

with this in mind see the corrected 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());
like image 99
Raphael Müller Avatar answered Oct 21 '22 17:10

Raphael Müller