ttous
ttous

Reputation: 406

Declaration of child method must be compatible with parent method

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 with A::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

Answers (3)

deceze
deceze

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

Alex Dupuis
Alex Dupuis

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

JParkinson1991
JParkinson1991

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

Related Questions