繁体   English   中英

埃菲尔:协变非法类型作为参数传递?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM