Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP interface implementation rejects subclasses on parameters

consider this:

class A{}

class B extends A{}

interface I{
 // expects object instanceof A
 function doSomething(A $a);
}

class C implements I
{
 // fails ????
 function doSomething(B $b){}
}

In my conception the above should work but it doesn't as php rejects that implementation requiring the first parameter to be exactly the same type (A) as defined in the interface (I). Since B is a subclass of A, I don't see whats the problem. Am I missing something here?

like image 707
fabio Avatar asked Jan 24 '11 13:01

fabio


2 Answers

class C implements I means that there must be subtype relation between C and I. It means object of type C should be usable wherever an object of type I is required.

In your case C is more restrictive than I because it has more precise requirements on its doSomething argument -- I.doSomething is fine with any A but C.doSomething requires a specific subtype of A

Note that if you change C.doSomething to accept any A then nothing prevents you to pass it an object of type B. You just can't require only B, because then you would break subtyping contract.

In theory, subtypes can be more liberal about their function arguments and more specific about their return types (but never vice versa, as it was in your case). In practice, a programming language may require that argument types in overridden methods must be same everywhere.

like image 139
Aivar Avatar answered Nov 15 '22 08:11

Aivar


In theory, subtypes can be more liberal about their function arguments and more specific about their return types (but never vice versa, as it was in your case). In practice, a programming language may require that argument types in overridden methods must be same everywhere.

little work around- instanceof to solve that problem:

class A{}

class B extends A{}

interface I{
 // expects object instanceof A
 function doSomething(A $a);
}

class C implements I
{

 function doSomething(A $b){
   if($b is instance of B){
   //do something
   }else{throw new InvalidArgumentException("arg must be instance of B") };
 }
}
like image 29
YAMM Avatar answered Nov 15 '22 08:11

YAMM