tl; dr:不带OO就可以继承,不带OO可以具有封装,不带OO可以具有多态性,甚至不带OO也可以同时具有这三个。另一方面,您可以拥有没有继承的OO。另外,有不同类型的封装(面向ADT和OO),IOW并非所有封装都是OO。
长版:
术语“面向对象编程”是Alan Kay发明的,因此他可以决定它的含义。而且他是这样定义的:
对我而言,OOP意味着仅消息传递,本地保留和保护以及状态过程的隐藏以及所有事物的极端后期绑定。
实现明智的,消息是后期绑定过程调用,如果过程调用后期绑定,那么你就不能在设计时知道什么你要电话,所以你不能对状态的具体表现做任何假设。因此,实际上是关于消息传递的,后期绑定是消息传递的一种实现,封装是它的结果。
后来他澄清了“ 大想法是'消息传递' ”,并遗憾地称其为“面向对象”而不是“面向消息”,因为术语“面向对象”将重点放在不重要的事物上(对象)并分散真正重要的内容(消息传递):
轻轻提醒一下,我在上一期OOPSLA上做了一些尝试,试图提醒大家,Smalltalk不仅是其语法或类库,甚至与类无关。很抱歉,我很久以前为该主题创造了“对象”一词,因为它使许多人专注于较小的想法。
最大的想法是“消息传递”-这就是Smalltalk / Squeak的核心所在(这在我们的Xerox PARC阶段中从未完全完成)。日语有一个小字-ma-代表“介于两者之间的事物”,也许最接近的英语是“ interstitial”。制作出色且可扩展的系统的关键在于设计模块的通信方式,而不是设计其内部属性和行为。想想互联网-要生存,它(a)必须允许超出任何单一标准的许多不同种类的想法和实现,并且(b)允许这些想法之间具有不同程度的安全互操作性。
(当然,今天,大多数人甚至不专注于对象,而是专注于类,这是错误的。)
消息是根本,以面向对象,无论是作为隐喻和作为一种机制。
如果您向某人发送消息,您将不知道他们如何处理该消息。在只有你可以观察到的东西,是他们的反应。您不知道他们是否自己处理消息(即对象是否具有方法),是否将消息转发给其他人(委托/代理),甚至他们是否理解。这就是封装的全部内容,这就是OO的全部内容。您甚至无法区分代理与真实对象,只要它能响应您的期望即可。
“消息传递”的一个更“现代”的术语是“动态方法分派”或“虚拟方法调用”,但它失去了隐喻,而专注于该机制。
威廉·R·库克(William R. Cook)重新审视的《关于理解数据抽象》以及他关于“简化的,现代的“对象”和“面向对象”定义的建议”中也提出了类似的观点。
动态分配操作是对象的基本特征。这意味着要调用的操作是对象本身的动态属性。无法静态识别操作,并且通常无法准确地响应给定请求执行什么操作,除非运行该操作。这与始终动态分配的一流函数完全相同。
在Smalltalk-72中,甚至没有任何物体!有仅是得到了分析,重写和重新路由信息流。首先出现的是方法(解析和重新路由消息流的标准方法),后来出现的是对象(共享某些私有状态的方法组)。继承来得晚了很多,而引入类只是作为支持继承的一种方式。如果Kay的研究小组已经了解原型,那么他们可能根本不会引入类。
每个程序员都应该阅读《重新理解数据抽象》。它详细解释了对象和抽象数据类型之间到底有什么区别。他给出了使用Java的例子,那就是对这个问题非常重要,因为在这两个的ADT的例子和他使用继承,封装和多态对象的实例,但只有一个的例子是面向对象!换句话说:您可以具有继承,封装和多态性,甚至可以同时拥有这三个,而仍然没有OO。
另一方面,您可以拥有没有继承的OO。就像我在上面暗示的那样:Smalltalk的原始版本(由“面向对象程序设计”一词的发明者Alan Kay设计的语言)没有继承。
最后但并非最不重要的一点是,《奥兰多条约》讨论了委托作为继承的一种替代方法,以及不同形式的委托和继承如何在面向对象语言的设计空间内导致不同的设计要点。(请注意,实际上,即使在支持继承的语言(如Java)中,人们实际上也被告知要避免使用继承,这再次表明对OO而言是不必要的。)