Eiffel:Covariant非法类型作为参数传递?

时间:2016-12-13 11:54:27

标签: covariance eiffel subtyping

(强调我的)

  

Covariant redefinition of fields and functions provides no problems, but covariant redefinition of arguments does create a problem that illegal types can be passed as arguments.

但是,如果重新定义字段和函数类型共同导致没有问题,那么 为什么如何共同重新定义一个论证的类型会导致麻烦?

协变重新定义等于子类型,对吧?而且亚型可以取代他们的超类型!

捕获的是什么?

2 个答案:

答案 0 :(得分:1)

问题不在于协方差本身。 (特别是,如果它是逆变型,那么按合同设计是不可能的,因为后代类特征中的参数类型不一定具有父母可用的特征。协方差不存在这样的问题。)< / p>

问题是协方差与多态性的结合。 E.g。

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呼叫(更改可用性或类型)。

这个问题的解决方案是避免将协方差与多态性一起使用,即调用不应该是多态的,或者不应该对参数进行协变重新声明。关于这个解决方案的工作正在进行中。

答案 1 :(得分:0)

&#34;呼叫不应该是多态的,或者不应该有协变的重新声明。&#34;

你怎么知道?

让我们改变你的榜样:

嗡嗡声(a_a:A) 做   a_a.foo(创建{A}) 端

这看起来很无辜。但是如果buzz收到动态类型B的参数,你仍然会得到嘘声。嗡嗡声的作者很可能处于B的存在未知的情况。

我认为你需要放弃&#34;呼叫不应该是多态的,或者#34;一点意见。只是禁止协变重新声明论点。