Php 子方法的声明必须与父方法兼容

Php 子方法的声明必须与父方法兼容,php,Php,这是我的密码: 我有一个类a,它有一个方法foo,该方法返回一个Bar对象 class A { public function foo(): Bar { //some ops return $bar; //'Bar' object } } class B extends A { public function foo(): BarX { //some ops return $barX; //'BarX' o

这是我的密码:

我有一个类
a
,它有一个方法
foo
,该方法返回一个
Bar
对象

class A {
    public function foo(): Bar {
        //some ops
        return $bar; //'Bar' object
    }
}
class B extends A {
    public function foo(): BarX {
        //some ops
        return $barX; //'BarX' object
    }
}
我还有一个类
B
,它扩展了类
a
,使用一个重写的方法
foo
,返回一个
BarX
对象

class A {
    public function foo(): Bar {
        //some ops
        return $bar; //'Bar' object
    }
}
class B extends A {
    public function foo(): BarX {
        //some ops
        return $barX; //'BarX' object
    }
}
重要的是条码
类扩展了
条码

当我运行代码时,在类
B
上有一个错误,说:

B::foo():Bar的声明必须与
A::foo():Bar兼容

既然
BarX
扩展了
Bar
,它们怎么会不兼容呢?我怎样才能解决这个问题呢


谢谢。

让Bar和BarX都实现一个接口,并将其作为返回类型

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

让Bar和BarX实现一个接口,并将其作为返回类型

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

您可以返回一个BarX,但由于B扩展了a,它必须返回相同的类型,但由于BarX是Bar,您可以这样做:

class B extends A {
    public function foo(): Bar {
        $barX = new BarX;
        //some ops
        return $barX; //'BarX' object
    }
}

您可以返回BarX,但由于B扩展了a,它必须返回相同的类型,但由于BarX是Bar,您可以这样做:

class B extends A {
    public function foo(): Bar {
        $barX = new BarX;
        //some ops
        return $barX; //'BarX' object
    }
}
仔细研究并考虑:

function (A $a) {
    $bar = $a->foo();
}
$bar
将成为
bar
还是
BarX
?你不知道。由于
$a
既可以作为
a
注入,也可以作为
B
注入(因为
B是a
的实例,因为
B扩展了a
),因此无法预测
$a
将是什么,也无法预测
$bar
将是什么

这就是为什么统一和可预测的界面很重要,这也是PHP抱怨的原因。

仔细研究并考虑:

function (A $a) {
    $bar = $a->foo();
}
$bar
将成为
bar
还是
BarX
?你不知道。由于
$a
既可以作为
a
注入,也可以作为
B
注入(因为
B是a
的实例,因为
B扩展了a
),因此无法预测
$a
将是什么,也无法预测
$bar
将是什么


这就是为什么统一和可预测的接口很重要,这也是PHP抱怨的地方。

考虑:
function(a$a){$b=$a->foo();}
——是
$b
a
Bar
还是
BarX
?你不知道。可以说,如果两种类型都兼容,那也没关系。但是你不应该在你的打字系统中有这样的反复无常。@deceze:是的,我有
$b
是一个
条形图
,因为
$a
是一个
a
对象,而
a
对象的
foo
方法返回
条形图
对象。在您的示例中没有
B
对象,
$B
怎么可能是
BarX
对象?既然
B
a
的子类,调用方还可以为
$a
注入
B
@deceze我理解:),所以我认为让两个
foo
函数都返回一个
Bar
是最好的解决方案,谢谢,我只是在写这个作为答案的过程中…:DConsider:
function(a$a){$b=$a->foo();}
-是
$b
a
Bar
还是
BarX
?你不知道。可以说,如果两种类型都兼容,那也没关系。但是你不应该在你的打字系统中有这样的反复无常。@deceze:是的,我有
$b
是一个
条形图
,因为
$a
是一个
a
对象,而
a
对象的
foo
方法返回
条形图
对象。在您的示例中没有
B
对象,
$B
怎么可能是
BarX
对象?既然
B
a
的子类,调用方还可以为
$a
注入
B
@deceze我理解:),所以我认为让
foo
函数返回
Bar
是最好的解决方案,谢谢,我只是在写这个作为答案的过程中…:DThanks@Goon3r,但实际上这意味着
a::foo()
B::foo()
方法可以返回
Bar
BarX
对象。这等于有:
A::foo():**Bar**
B::foo()**Bar**
…这使得界面变得无用,不是吗?谢谢@Goon3r,但实际上这意味着
A::foo()
B::foo()
方法都可以返回
Bar
BarX
对象。这等于有:
A::foo():**Bar**
B::foo()**Bar**
…这使得界面毫无用处,不是吗?是的,我想我除了做soYep别无选择,我想我除了做soYep别无选择