不允许 Circle 实例接受 Point3D 作为中心
Unallow a Circle instance to accept a Point3D as center
我想提交一个 OOP 问题。也许它已经在其他地方解决了,但我找不到它...
想象一下这样的事情(python-类似伪代码)
class Point:
x: int
y: int
# Some methods here
class Point3D(Point):
z: int
class Circle:
center: Point
radius: int
# Some methods here
class Sphere(Circle):
center: Point3D
在静态类型语言中 - 除非我犯错 - Point3D
实例将作为 Circle
的 center
属性传递,因为它继承自 Point
, 这是不允许的,因为它会变成 Sphere
-like.
我们如何在不丢失方法分解的情况下实现这一点?
Liskov Substitution Principle (LSP) 声明用派生 class 的实例替换基 classe 的实例将始终有效。这是 OOP 的核心特性,不是问题。
问题出在你的模型上 -- 让我们考虑一下 2D 点和 3D 点之间的关系是什么。 Point3D
继承自 Point2D
表示 Point3D
是 Point2D
,即所有 Point3D
也是 Point2D
的。
但这实际上并不适合您的模型!在数学中,只有来自 2D 平面的 3D 点(带有 z == 0
的点)实际上是 2D 点。这种差异是可能将您的 Circle
变成球体的漏洞的来源。
这个 OOP 模型实际上可能是相反的:所有 2D 点 都是 3D 点,z == 0
。因此 Point2D
继承自 Point3D
是有道理的。但是,它会带来一系列新的可变性问题:如果您能够将 Point2D
作为 Point3D
访问并修改它,那么您可以将其 z
坐标设置为非零,并以不一致的 Point2D
结束,它实际上不再是 2D。 LSP又坏了
很容易在 OOP 中以任一方向表示 2D 和 3D 点之间的关系:
- 一个 3D 点包含一个 2D 点不使用的坐标,因此它应该是派生的 class
...或...
- 在数学上,一个2D点也是一个3D点,所以它应该是导出的class
...但最重要的是 class 都不能从另一个 继承,因为 LSP 无论如何都会被破坏。将它们保持为单独的 classes,apples with apples 和 Circle
s with Point2D
s,如果您需要在点之间分解公共代码,请使用一些其他语言功能——泛型编程,例如例如。
我想提交一个 OOP 问题。也许它已经在其他地方解决了,但我找不到它...
想象一下这样的事情(python-类似伪代码)
class Point:
x: int
y: int
# Some methods here
class Point3D(Point):
z: int
class Circle:
center: Point
radius: int
# Some methods here
class Sphere(Circle):
center: Point3D
在静态类型语言中 - 除非我犯错 - Point3D
实例将作为 Circle
的 center
属性传递,因为它继承自 Point
, 这是不允许的,因为它会变成 Sphere
-like.
我们如何在不丢失方法分解的情况下实现这一点?
Liskov Substitution Principle (LSP) 声明用派生 class 的实例替换基 classe 的实例将始终有效。这是 OOP 的核心特性,不是问题。
问题出在你的模型上 -- 让我们考虑一下 2D 点和 3D 点之间的关系是什么。 Point3D
继承自 Point2D
表示 Point3D
是 Point2D
,即所有 Point3D
也是 Point2D
的。
但这实际上并不适合您的模型!在数学中,只有来自 2D 平面的 3D 点(带有 z == 0
的点)实际上是 2D 点。这种差异是可能将您的 Circle
变成球体的漏洞的来源。
这个 OOP 模型实际上可能是相反的:所有 2D 点 都是 3D 点,z == 0
。因此 Point2D
继承自 Point3D
是有道理的。但是,它会带来一系列新的可变性问题:如果您能够将 Point2D
作为 Point3D
访问并修改它,那么您可以将其 z
坐标设置为非零,并以不一致的 Point2D
结束,它实际上不再是 2D。 LSP又坏了
很容易在 OOP 中以任一方向表示 2D 和 3D 点之间的关系:
- 一个 3D 点包含一个 2D 点不使用的坐标,因此它应该是派生的 class
...或...
- 在数学上,一个2D点也是一个3D点,所以它应该是导出的class
...但最重要的是 class 都不能从另一个 继承,因为 LSP 无论如何都会被破坏。将它们保持为单独的 classes,apples with apples 和 Circle
s with Point2D
s,如果您需要在点之间分解公共代码,请使用一些其他语言功能——泛型编程,例如例如。