实现继承,语言缺陷

标签: 继承 语言 | 发表时间:2011-08-15 23:26 | 作者:dreamhead 2sin18
出处:http://dreamhead.blogbus.com

zhaorui在《When You Click…》回复:
“实现继承是某种程度上的语言缺陷” 这个我也不太理解,是否可以解释一下

好,那就解释一下。

面向对象的三个特征是什么?一个本科毕业生都可以对答如流:继承、封装和多态。在常规的理解中,继承分为实现继承和接口继承。简单说,实现继承就是为了把代码拿过来复用,而接口继承是给多态做准备。

面向对象和基于对象的差别就在于多态,程序是不是面向对象,看看有没有多态就知道了。我们还提倡面向接口编程,探究is-a关系,讲求各种各样的设计原则,讨论各种各样的设计模式。但仔细想一下就会发现,所有这些讨论都是围绕着多态,也就是接口继承的,跟实现继承没有任何关系。

那实现继承为什么还如此阴魂不散的围绕在我们身边呢?

最早大面积流行的面向对象程序设计语言是C++,所以,C++的选择影响了很多人,包括后来者Java和C#。所以,很多程序员一想到继承,就会想到把一些方法抽到基类里面,也有很多人愿意为了实现一个集合类,让自己的类继承自某个collection。其实,我们真正想要的不是继承,而只是要把一些公共操作放到一个地方,方便复用。

有了实现继承,随之而来会有很多问题,其中最著名的莫过于钻石问题。它的根源在于多重继承,绝大多数使用多重的场景只是为了从别人那里拿个实现过来。许多新语言都惟恐避之不及的躲开多重继承,事实证明,没多重继承,我们依然活着,还活得挺好。

如果你的世界里只有C++/Java/C#,那这是个让人头疼的问题,虽然有人会告诉你,少用继承,多用组合。但你也知道,写一大堆delegate,也挺讨厌的。说白了,语言不给力。

好吧!你知道我要说语言的事了。如果了解过Ruby,你应该知道module,如果你是个Scala程序员,trait是个利器。某种程度上说,C#的extension method也能做这件事。这些语言特性都能很好的解决真正的问题:代码复用。我们只要把需要复用的代码放到module/trait/extension method里,复用的问题就迎刃而解了,而无需小才大用的使用继承。

其实,如果语言可以解决复用的问题,那么,仔细想一下,我们会发现某些设计不甚合理的地方,比如Rails里面,Model为什么要从ActiveRecord::Base继承而来,我们只是需要某些能力而已,这样的话,也许把ActiveRecord::Base实现成一个module更为合理。

仔细了解一下语言的实现,我们不难发现,这些机制往往是在底层通过继承实现的。这从另外一个角度说明,或许实现继承本身就应该是一个底层实现,而非语言层面上的东西。

对于程序员来说,只会一门语言或一系列类似的语言,无疑于手里只有锤子,那时,眼里都是钉子,闭塞得很,可惜,这是大多数程序员的现状。

相关 [继承 语言] 推荐:

实现继承,语言缺陷

- 2sin18 - 梦想风暴
zhaorui在《When You Click…》回复:. “实现继承是某种程度上的语言缺陷” 这个我也不太理解,是否可以解释一下. 一个本科毕业生都可以对答如流:继承、封装和多态. 在常规的理解中,继承分为实现继承和接口继承. 简单说,实现继承就是为了把代码拿过来复用,而接口继承是给多态做准备. 面向对象和基于对象的差别就在于多态,程序是不是面向对象,看看有没有多态就知道了.

javascript继承的写法

- LiuWeifeng - 断桥残雪部落格
严格来说javascript是基于对象而不是面向对象的语言,因为javascript没有像java语言那么丰富的类、继承、封装,但是javascript是基于原型(prototype)的面向对象开发,是一种动态、弱类型、基于原型的语言. 前几天看了阿里UED的《重温javascript继承机制》,今天重新看了,很有感触,特地转载了重要的部分,记录一下,下次有需要的时候还要重新看一下.

JPA 实现继承关系

- - ITeye博客
JPA支持继承关系,使开发者可以利用继承的思想建模.        有一个实体Person,他是一个抽象实体,他有两个子实体:Man,Woman.        先写Person类:. //@DiscriminatorColumn(name="tableName")可选. 注意,对于抽象父类,必须设置两个注释:.

JavaScript继承方式详解

- - SegmentFault 最新的文章
js里常用的如下两种继承方式:. 原型链继承(对象间的继承) 类式继承(构造函数间的继承). 由于 js不像 java那样是真正面向对象的语言, js是基于对象的,它没有类的概念. 所以,要想实现继承,可以用 js的原型 prototype机制或者用 apply和 call方法去实现.

多重继承及虚继承中对象内存的分布

- Michael - 淘宝数据平台与产品部官方博客 tbdata.org
这篇文章主要讲解G++编译器中虚继承的对象内存分布问题,从中也引出了dynamic_cast和static_cast本质区别、虚函数表的格式等一些大部分C++程序员都似是而非的概念. 问题拿捏得十分到位,下面是我对原文的翻译,原文见这里(By Edsko de Vries, January 2006).

Javascript继承机制的设计思想

- David - 阮一峰的网络日志
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototype chain)模式,来实现继承. 我花了很多时间,学习这个部分,还做了很多笔记. 但是都属于强行记忆,无法从根本上理解.

JavaScript 类/函数继承最佳实践

- - idea's blog
JavaScript 没有像 Java 等面向对象语言的 class 关键字用法, 和 class 最像的就是 function 了. 下面的代码相当于在 JavaScript 中定义了一个类:. 如果想新定义一个类 Child 继承 Base, 怎么办. JavaScript 又没有 extends.

JavaScript 函数、作用域和继承

- - 幸福收藏夹
关于函数、作用域和继承,可以写的非常多. 不过和 JavaScript 类型浅解 一样,是写给初学者看的,我们着重从简单的来. 当然,即使用「简单」来描述,这也是 JavaScript 中最不容易懂的点之一. 如你所见, function fn(){},像这个声明式函数. 虽然初学看起来有点乱,不过我想说的是,你总会知道如何用的,现在知道就可以了.

JavaScript中的原型和继承

- - 博客园_知识库
   英文原文: Prototypes and Inheritance in JavaScript.   请在此暂时忘记之前学到的面向对象的一切知识.   最近我正在观看  24 Hours of Le Mans ,这是法国流行的一项赛事. 最快的车被称为 Le Mans 原型车. 这些车虽然是由“奥迪”或“标致”这些厂商制造的,可它们并不是你在街上或速公路上所见到的那类汽车.

语言壁垒

- kylexlau - Chun Tian (binghe)
虽然经常更新微博,但确实又有些日子没写常规博客了. 10 月开始前有必要再写一篇,整理一下近期的各种思路,以良好的精神面貌迎接今年的最后一个季度. 首先发布一个已经不太新的消息:Practical Common Lisp 的中文版《实用 Common Lisp 编程》几经周折终于付印了,下月即可正式出版;读者们甚至已经可以在当当网上预订了.