java inheritance_subtyping和inheritance的区别是什么?

@大笨蛋千里冰封 你还是没懂嘛……上次你提到这个之后,我特别查了相关资料,真好你就听我废话一会儿吧。

首先,因为一部分编程语言把这两个概念揉起来了(比如java),声明subtyping关系时同时声明inheritance关系,这可能导致了你(还有我)一开始的混淆。

首先声明,java对inheritance的这种称呼是不对的。extends在声明它所谓的inheritance关系的时候不但声明了inheritance关系,同时也声明了subtyping关系。

subtyping注重的是建立一种"is a"的关系,同时它的本质是与另一类型建立substitutability。而这个substitutability是通过Liskov Substitution Principle定义的:Subtype Requirement: Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T.

Subtype要求:如果S是一个T的subtype,而Φ(x)是一个对与类型T的实体(在程序语言中就是一个term,但是说是object更加universal)x可被证明的属性,那么Φ(y)应该对所有具有类型S的实体y为真。

subtyping是一种在semantics上定义的关系,引用Wikipedia,“safely used in a context where”的关系。它注重的是类型本身的substitutability,或者说compatibility,当A <: b s is a subtype of t the subtyping relation often written to mean that any term type can be safely used in context where expected.>

如果S是T的一个subtype——这种关系常被写为S <: t>

用java举个例子:

interface T {}

class S implements T {}

S a = new S();

T b = a;

这里面的第四行就是上面说的a context where a term of type T is expected,同时你也可以看到,同时通过你的java的直觉感受到,将具有(或者被推导出?推导出应该是TaPL的术语,不知道哪个更准确,有知道的人可以告诉我一下)S类型的term a使用在一个需要类型T的term的context(也就是T b = ;)中是安全的。

注意我这里用了interface,因为在java8之前implements所声明的关系就是纯粹的subtyping关系,我下面说完inheritance的定义再说这个。

Inheritance的定义是reuse of implementations。Inheritance可以被定义为:A type B inherits from another type A if some functions for B are written in terms of functions of A.

如果类型B的某些函数是由类型A的某些函数的term构成的,那么说类型B是继承自类型A的。

这个我在Princeton的CS School的某个纯静态页面上找出来的一句话我觉得是真的一语道破,比Wikipedia这啰啰嗦嗦一大堆(我就不翻译了……)In object-oriented programming, inheritance is when an object or class is based on another object (prototypal inheritance) or class (class-based inheritance), using the same implementation (inheriting from an object or class) or specifying a new implementation to maintain the same behavior (realizing an interface; inheriting behavior; programming by difference[1]). Such an inherited class is called a subclass of its parent class or super class. It is a mechanism for code reuse and to allow independent extensions of the original software via public classes and interfaces. The relationships of objects or classes through inheritance give rise to a hierarchy. Inheritance was invented in 1967 for Simula.[2] The term "inheritance" is loosely used for both class-based and prototype-based programming, but in narrow use is reserved for class-based programming (one class inherits from another), with the corresponding technique in prototype-based programming being instead called delegates to another).

Inheritance should not be confused with subtyping.[3][4] In some languages inheritance and subtyping agree,[a] whereas in others they differ; in general, subtyping establishes an is-a relationship, whereas inheritance only reuses implementation and establishes a syntactic relationship, not necessarily a semantic relationship (inheritance does not ensure behavioral subtyping). To distinguish these concepts, subtyping is also known as interface inheritance, whereas inheritance as defined here is known as implementation inheritance or code inheritance.[5] Still, inheritance is a commonly used mechanism for establishing subtype relationships.[6]

要好多了,不过,我仍然想要你读第二段,它用比我精简一点点的语言说明了这俩的不同。

然后,刚刚那一句关于reuse的定义,根据term和type的定义可能抽象了点,但是其实它很简单。用java的概念理解就是,你写了extends之后,superclass中的public和protected method都跑到当前这个类里面了,这就是inheritance。

然后还有,java程序员们口中说的polymorphism,指的是subtyping polymorphism(inclusion polymorphism,我终于查到这个名字了,上次有人告诉我叫subtyping polymorphism之后我就觉得它还有个名字),是subtyping而不是inheritance。Inheritance的唯一一个定义就是reuse of implementations,所以,它不带来任何polymorphism和substitutability的保证。

回到刚刚那段代码,我相信你也明白了为什么java8之前的implements就是纯粹地声明subtyping relation。如果没有default method,那么interface中声明的method就是LSP中提到的property的声明,同时subtyping relation的建立的确满足了LSP。而extends以及implement一个带有default method的interface事实上是同时建立了subtyping和inheritance关系(从这一点上,我很好奇为什么Scala不把subtyping和inheritance的声明语法分开提供,可能的确分开没啥实际意义吧,毕竟Wikipedia中也提到大部分OO语言实现subtyping的方式就是进行inheritance,估计是想要说这两个密不可分吧)。

所以做个summary,subtyping是compatibility of interfaces,inheritance是reuse of implementations,你可以发现在java中,这两个都是inheritance的特性,于是我们刚刚把这个万恶的被混淆的概念分成了两个清晰的概念。

下面还有几个我查资料的时候看到的想要提到的东西,首先第一个是In a number of object-oriented languages, subtyping is called interface inheritance, with inheritance referred to asimplementation inheritance.

在很多OO语言中,subtyping被称作接口继承,而inheritance则被称为实现继承。

这个就是个细节了,说subtyping polymorphism和inheritance可能是比较formal的说法,然后当你讨论OO语言的时候,可以用这两个术语。我在查资料的时候这两个的确出现过,所以你知道这俩是一个东西就好。

然后Wikipedia中还提到了,关于inheritance的两种主要实现形式(不是OO中的inheritance,就是formal defined inheritance),prototype inheritance和class inheritance,和你的题目没啥关系就不展开说了,提一下你自己去查。

还有一个,LSP其实是几个很常见的性质的基础,这些性质包括,a) subtype中方法参数类型的contravariance b) subtyping中方法返回值类型的covariance c) 对于某个subtype中的方法,它不能抛出新的异常,除非那个异常是supertype抛出的异常的subtype(注意subtype根据LSP的定义,是包括其本身的,T <: t>

好了,我废话完了……不知道你这次理解了没有。

(不知道会不会有我理解错的或是说的不对的啊……我自己查应该没有,不过要是有的话就在评论里使劲喷我吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值