为什么要避免子类型化? [英] Why avoid subtyping?

查看:18
本文介绍了为什么要避免子类型化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Scala 社区中看到很多人建议避免像瘟疫一样"使用子类型.反对使用子类型的各种原因是什么?有哪些替代方案?

I have seen many people in the Scala community advise on avoiding subtyping "like a plague". What are the various reasons against the use of subtyping? What are the alternatives?

推荐答案

类型决定了组合的粒度,即可扩展性.

Types determine the granularity of composition, i.e. of extensibility.

例如,一个接口,例如Comparable,它结合了(因此混为一谈)等式和关系运算符.因此,不可能只在相等或关系接口之一上进行组合.

For example, an interface, e.g. Comparable, that combines (thus conflates) equality and relational operators. Thus it is impossible to compose on just one of the equality or relational interface.

一般来说,继承的替代原则是不可判定的.罗素悖论意味着任何可扩展的集合(即不枚举每个可能的成员或子类型的类型),都可以包含自身,即是自身的子类型.但是为了识别(决定)什么是子类型而不是它自己,它本身的不变量必须被完全枚举,因此它不再是可扩展的.这就是子类型可扩展性使继承不可判定的悖论.这个悖论必须存在,否则知识将是静态的,因此知识形成将不存在.

In general, the substitution principle of inheritance is undecidable. Russell's paradox implies that any set that is extensible (i.e. does not enumerate the type of every possible member or subtype), can include itself, i.e. is a subtype of itself. But in order to identify (decide) what is a subtype and not itself, the invariants of itself must be completely enumerated, thus it is no longer extensible. This is the paradox that subtyped extensibility makes inheritance undecidable. This paradox must exist, else knowledge would be static and thus knowledge formation wouldn't exist.

函数组合是子类型化的满射替换,因为函数的输入可以替换它的输出,即在任何需要输出类型的地方,输入类型可以被替换,方法是将它包装在函数调用中.但是组合并不构成子类型的双射契约——访问函数输出的接口,不访问函数的输入实例.

Function composition is the surjective substitution of subtyping, because the input of a function can be substituted for its output, i.e. any where the output type is expected, the input type can be substituted, by wrapping it in the function call. But composition does not make the bijective contract of subtyping-- accessing the interface of the output of a function, does not access the input instance of the function.

因此组合不必保持未来(即无界)不变量,因此可以既可扩展又可判定.在可证明可判定的情况下,子类型可以很多更强大,因为它维护了这种双射契约,例如一个对超类型的不可变列表进行排序的函数,可以对子类型的不可变列表进行操作.

Thus composition does not have to maintain the future (i.e. unbounded) invariants and thus can be both extensible and decidable. Subtyping can be MUCH more powerful where it is provably decidable, because it maintains this bijective contract, e.g. a function that sorts a immutable list of the supertype, can operate on the immutable list of the subtype.

所以结论是枚举每种类型(即其接口)的所有不变量,使这些类型正交(最大化组合粒度),然后使用函数组合来完成那些不正交的扩展.因此,子类型仅适用于可证明对超类型接口的不变量建模的情况,并且子类型的附加接口可证明与超类型接口的不变量正交.因此接口的不变量应该是正交的.

So the conclusion is to enumerate all the invariants of each type (i.e. of its interfaces), make these types orthogonal (maximize granularity of composition), and then use function composition to accomplish extension where those invariants would not be orthogonal. Thus a subtype is appropriate only where it provably models the invariants of the supertype interface, and the additional interface(s) of the subtype are provably orthogonal to the invariants of the supertype interface. Thus the invariants of interfaces should be orthogonal.

范畴理论为每个子类型(即 Functor、Applicative 和 Monad)的不变量的模型提供规则,其中 保留提升类型上的函数组合,即参见前面提到的列表子类型化的威力示例.

Category theory provides rules for the model of the invariants of each subtype, i.e. of Functor, Applicative, and Monad, which preserve function composition on lifted types, i.e. see the aforementioned example of the power of subtyping for lists.

这篇关于为什么要避免子类型化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆