[英]Eiffel: Covariant illegal types passed as arguments?
(强调我的)
但是,如果重新定义字段和函数类型没有问题,那么如何重新定义参数的类型又会带来麻烦呢?
协变重定义等于子类型,对吗? 子类型可以代替它们的超类型!
有什么收获?
问题不在于协方差本身。 (特别是,如果是相反方差,则按合同设计是不可能的,因为后代类特征中的参数类型不必在其父级中具有可用特征。使用协方差时就不会出现这样的问题。)
有问题的是协方差与多态性的结合。 例如
class A feature
foo (a: A) do a.bar end -- (1)
bar do end
end
class B inherit A redefine foo end feature
foo (a: B) do a.qux end -- (2)
qux do end
end
现在,以下代码将崩溃:
a: A; b: B
...
create b
a := b
a.foo (create {A})
实际上, a.foo
将调用版本(2),因为a
附加到类型B
的对象上。 但是,传递给此功能的参数将为A
类型。 并且A
没有导致运行时错误的功能qux
。 这种错误称为CAT调用( 更改可用性或类型 )。
解决此问题的方法是避免将协方差与多态性一起使用,即调用不应是多态的,或者不应有参数的协变重新声明。 此解决方案的工作正在进行中。
“调用不应该是多态的,也不应该对参数进行协变重新声明。”
你怎么知道?
让我们更改一下示例:
嗡嗡声(a_a:A)执行a_a.foo(创建{A})结束
这看起来很无辜。 但是,如果buzz收到动态类型B的参数,您仍然会收到catcall。 嗡嗡声的作者很可能处于B的存在未知的情况。
我认为您需要删除“呼叫不应是多态的”或一些建议。 只需禁止参数的协变重新声明即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.