Reputation: 406
Here's my code :
I have a class A
, with a method foo
, that returns a Bar
object.
class A {
public function foo(): Bar {
//some ops
return $bar; //'Bar' object
}
}
I also have a class B
, that extends class A
, with an overridden method foo
, that returns a BarX
object.
class B extends A {
public function foo(): BarX {
//some ops
return $barX; //'BarX' object
}
}
What is important is that the BarX
class extends the Bar
class.
When I run my code, I have an error on class B
, saying :
Declaration of
B::foo(): BarX
must be compatible withA::foo(): Bar
How are they not compatible since BarX
extends Bar
? And how could I fix this problem please ?
Thank you.
Upvotes: 0
Views: 110
Reputation: 522005
Study the L in SOLID carefully and consider:
function (A $a) {
$bar = $a->foo();
}
Is $bar
going to be a Bar
or BarX
? You don't know. Since $a
can be injected either as an A
or B
(because B instanceof A
, because B extends A
), you can't predict what $a
will be and hence what $bar
will be.
That's why a uniform and predictable interface is important and that's what PHP complains about.
Upvotes: 1
Reputation: 366
You can return a BarX but since B extends A, it must return the same type but since BarX is Bar, you can do it like that:
class B extends A {
public function foo(): Bar {
$barX = new BarX;
//some ops
return $barX; //'BarX' object
}
}
Upvotes: 1
Reputation: 1286
Have both Bar and BarX implement an interface and have that as you're return type.
<?php
interface BarInterface(){ }
class Bar implements BarInterface(){ }
class BarX implements BarInterface(){ }
class A {
public function foo(): BarInterface {
//some ops
return $bar; //'Bar' object
}
}
class B extends A {
public function foo(): BarInterface {
//some ops
return $barX; //'BarX' object
}
}
Upvotes: 2