首页 > 解决方案 > 是否可以在 PHP 中用类属性中的子级替换父级?

问题描述

如果应用多态性,应该可以在任何地方用孩子替换父母,因为孩子包含所有必要的属性。它总是满足父类接口。此外,它可以扩展它。

这是一个非常简化的示例:

class A {
    public int $x;
}

class B extends A {
    public int $y;
}

class C {
    public A $ca;
}

class D extends C {
    public B $ca;
}

$vd = new D();
$vd->cd->x = 10;

echo $vd->cd->x;

错误:D::$ca 的类型必须是 A(如在 C 类中)

AC在库和类中BD覆盖它们。

标签: phpoop

解决方案


类型化的属性在 PHP中是不变的。

来自类型属性的原始 RFC

属性类型是不变的。这意味着在继承期间不允许更改(非私有)属性的类型(这包括添加或删除属性类型)。如果父属性是私有的,那么类型可以任意改变。

属性类型不变的原因是它们既可以被读取也可以被写入。从 int 到 ?int 的更改意味着从属性读取现在除了整数之外还可能返回 null。从 ?int 到 int 的更改意味着不再可能将 null 写入属性。因此,逆变和协变都不适用于属性类型。

可以安全地做的是使用预期实例B实例:A


class C {
    public A $ca;
}

$c = new C();
$c->ca = new B();

...因此满足了Liskov 替换原则,即“如果 S 是 T 的子类型,则 T 类型的对象可以被 S 类型的对象替换”


推荐阅读