类型-子类型关系。似乎有些不清楚
我正在阅读面向对象编程语言课程的一些幻灯片,并深入了解类型子类型定义:
Barbara Liskov,“数据抽象和层次结构”,SIGPLAN 通知, 23,5(1988 年 5 月):
这里想要的是一些东西 就像下面的替换 属性:如果对于每个对象o_s 类型 S 有一个对象 o_T 输入 T 使得对于所有程序 P
根据 T 定义,行为 当 o_S 为时 P 不变 替换 o_T 那么 S 是 a T 亚型
那么它有一个例子:
点 = { x:整数, y:整数 }
正点 = { x:正, y:正 }
其中 Positive = { k:Integer | k> 0 }我们可以说 PositivePoint ≤ Point 吗?
是的,因为 PositivePoint 类型的元素可能总是 替换程序中定义的 Point 类型的元素 点条款!
现在...对我来说,似乎应该完全相反:Point ≤ PositivePoint,因为我无法在使用带有负坐标的 Point 的程序中使用 PositivePoint,而我可以相反。
我怀疑语法是Type ≤ Sub-type
还是Sub-Type ≤ Type
,但是这样的说法似乎更清楚,那是哪里出了问题呢?
编辑
只是为了让事情变得更容易,问题是: 你能说 PositivePoint
是 Point
的子类型吗? 为什么?
第二次编辑
我在这里报告我在评论中写的内容,希望它能让我的问题更清楚:
假设程序要画一个 从
点
开始的方形地图(-100,-100) 到点
(100, 100)。什么会 如果你使用类型就会发生正点
?该程序的 行为不变?不会的。 这种“不变的行为”是唯一的 我不明白的事情。如果定义 子类型只是继承并且 从其他类型重写
应该没问题,但似乎不行 案例。
I'm reading some slides of a class on object oriented programming languages and stepped into the type-subtype definition:
Barbara Liskov, “Data Abstraction and Hierarchy,” SIGPLAN Notices,
23,5 (May, 1988):
What is wanted here is something
like the following substitution
property: If for each object o_s of
type S there is an object o_T of
type T such that for all programs P
defined in terms of T, the behavior of
P is unchanged when o_S is
substituted for o_T then S is a
subtype of T
Then it goes with an example:
Point = { x:Integer, y:Integer }
PositivePoint = { x:Positive, y:Positive }
where Positive = { k:Integer | k > 0 }Can we say that PositivePoint ≤ Point?
Yes, because an element of type PositivePoint may always
replace an element of type Point in a program defined in
Point terms!
Now... for me it seems it should be quite the opposite: Point ≤ PositivePoint because I couldn't use PositivePoint in a program that uses Point with negative coordinates, while I could to the opposite.
I doubted if the syntax was Type ≤ Sub-type
or Sub-Type ≤ Type
, but the statement seems more clear, what's wrong then?
Edit
Just to make things easier the question is:
Can you say that PositivePoint
is a subtype of Point
?
Why?
2nd Edit
I report here what I wrote in a comment hoping it will make my problem clearer:
Suppose that the program has to draw a
square map fromPoint
(-100, -100)
toPoint
(100, 100). What would
happen if you use typePositivePoint
? Would the program's
behavior be unchanged? It would not.
This "unchanged behavior" is the only
thing I don't get. If the definition
of subtype was simplyinheriting and
from an other type it
overriding
would be ok, but it doesn't seem to be
the case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Liskov 是正确的,PositivePoint ≤ Point,因为 PositivePoint 是 Point 的细化。任何使用 Point 的代码也必须能够使用 PositivePoint,因为Point 的坐标始终有可能为正。反之则不然,因为使用 PositivePoint 的代码可能会在坐标始终为正的假设下运行,而用 Point 替换 PositivePoint 将打破该假设。
请注意,她并不是说 PositivePoint 可以替代 Point,只是说 PositivePoint 可以用在需要 Point 的地方。
Liskov is correct, PositivePoint ≤ Point, because PositivePoint is a refinement of Point. Any code that uses Point must also be able to use PositivePoint, because there was always the possibility that Point's coordinates were positive anyway. The reverse is not true, because code using PositivePoint may act under the assumption that the coordinates are always positive, and replacing PositivePoint with Point would break that assumption.
Note that she's not saying that a PositivePoint can replace a Point, just that a PositivePoint can be used where a Point is needed.
您可以通过子集对类型关系进行建模。
PositivePoint ⊂ Point
成立的原因与PositiveInt ⊂ Int
成立的原因相同:正数是所有可能数字的子集!每个
PositivePoint
都属于Point
,但反之则不然。You can model the type relationships through subsets.
PositivePoint ⊂ Point
holds for the same reason asPositiveInt ⊂ Int
does: Positive numbers are a subset of all possible numbers!Every
PositivePoint
belongs to thePoint
s, but not other way round.这个想法是,任何接受 PositivePoint 的函数都依赖于该点的值为正的事实。如果您传入一个值为非正数的 Point,则假设为假,函数将失败。
然而,接受 Point 的函数不会对该点的正性做出任何假设,因此如果您传入 PositivePoint,那就没问题了。
请注意,这仅适用于不可变的 Point 类。如果您能够更改 Point 的值,则 PositivePoint 和 Point 可能根本不存在子类关系,因为对于 PositivePoints,
px = -1
操作将会失败。编辑:详细说明:
假设我们有一个二维数组,它在需要时自动增长(即,当传递两个正索引时,您永远不会遇到索引越界错误)。现在我们有一个函数,它接受 PositiveInteger p,然后访问索引 x,y 处的二维数组。这不会失败,因为 x 和 y 保证为正,并且 2d 数组可以使用任何一对正索引进行索引。然而,如果 Point 是 PositivePoint 的子类型,则 p 实际上可能具有负值,即使它被声明为正值。这意味着使用它来索引数组不再安全。
然而,接受 Point 的函数不知道该点的值是负值还是正值 - 它已经必须考虑它们为正值的可能性。所以传入 PositiveInteger 不会破坏任何东西。
The idea is that any function which accepts a PositivePoint relies on the fact that the point's values are positive. If you passed in a Point whose values are not positive, the assumption is false and the function would fail.
A function accepting a Point, however, would make no assumptions about the point's positiveness, so if you passed in a PositivePoint, it would be fine.
Note that this is only true for an immutable Point class. If you were able to change a Point's value, PositivePoint and Point could be in no subclass relationship at all because the operation
p.x = -1
would fail for PositivePoints.Edit: To elaborate:
Let's say we have 2 dimensional array which automatically grows when required (i.e. you never get an index-out-of-bounds error when passing two positive indices). Now we have a function which accepts a PositiveInteger p and then accesses the 2d-array at index x,y. This can't fail because x and y are guaranteed to be positive and the 2d-array can be indexed with any pair of positive indices. However if Point was a subtype of PositivePoint, p could actually have negative values even though it's declared to be positive. This would mean that it's no longer safe to use it to index the array.
However a function accepting a Point doesn't know whether the point's values are negative or positive - it already has to take into account the possibility that they're positive. So passing in a PositiveInteger can't break anything.
我以前没有见过用来表示这一点的 ≤ 符号,但我认为
PositivePoint ≤ Point
的含义意味着Point
比Point 具有更大的潜在值范围code>PositivePoint
(即:PositivePoint
是Point
的子集,PositivePoint
的所有实例都可以替换为点
,但反之则不然。)I haven't seen the ≤ symbol used to denote this before, but what I think is meant by
PositivePoint ≤ Point
means thatPoint
has a greater range of potential values thanPositivePoint
(i.e.:PositivePoint
is a subset ofPoint
, all instances ofPositivePoint
could be replaced by a valid instance ofPoint
, but not the other way around.)