php - 是否可以在 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 类中)
类A
和C
在库和类中B
并D
覆盖它们。
解决方案
类型化的属性在 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 类型的对象替换”
推荐阅读
- visual-studio - Visual Studio 19 中缺少 HockeyApp
- java - 无法使用 jackson.databind 从 DB 反序列化 json 对象
- java - 在偏移提交时,Kafka 不知道分区,但没有发生重新平衡
- android - pub get failed: 因为flutter_app依赖firebase_firestore ^0.12.7+1 不匹配任何版本,版本解析失败
- json - JSON通过KNIME解析到表
- ip - 使用带有 IP 地址的 XMPPTCPConnectionConfiguration 和 setHost() 连接失败
- haskell - 如何在 Haskell 中使用 toList 和 Oset
- fortran - Intel 和 Gnu Fortran 编译错误
- apache-spark - Jupyter Notebook 中的 Spylon-kernel 引发“无法运行程序“python”错误”
- javascript - 进行不完全继承时的 instanceof 行为