什么使一种编程语言成为面向对象的语言?

37

既然没有有意义的术语的辩论是无意义的,我想我会指出房间里的大象并问:到底什么使一种语言成为“面向对象的”?我这里不是在寻找教科书式的答案,而是基于您在您所处领域中使用良好的OO语言的经验。

一个相关的问题可能有助于首先回答:什么是面向对象语言的原型以及为什么?

16个回答

32

面向对象的定义当然是一个棘手的问题, 但以下是我的观点:

对我而言,面向对象编程就是通过发送消息来协作的对象。对我而言,这是面向对象语言中最重要的特征。

如果我必须列出一个面向对象语言必须具备的所有特征的有序列表,它将如下所示:

  1. 对象向其他对象发送消息
  2. 一切都是对象
  3. 晚期绑定
  4. 子类型多态性
  5. 继承或类似表达方式,如委托
  6. 封装
  7. 信息隐藏
  8. 抽象化
显然,这个列表非常有争议,因为它排除了许多被广泛认为是面向对象的语言,比如JavaC#C++,它们都违反了1、2和3号点。然而,毫无疑问,这些语言允许面向对象编程(但C也可以),甚至更容易实现(而C不行)。因此,我称满足这些要求的语言为“纯面向对象”。
作为典型的面向对象语言,我会提到SelfNewspeak
两者都满足上述要求。它们都受到Smalltalk的启发并成为其继承者,在某种程度上实际上都更加“面向对象”。我喜欢Self和Newspeak的原因是它们都将消息发送范例推向了极致(Newspeak甚至比Self还要更进一步)。
在新语言中,所有都是消息发送。没有实例变量、字段、属性、常量或类名。它们都是通过使用getter和setter来模拟的。
在Self中,没有类,只有对象。这强调了面向对象的真正含义:对象而不是类。

1
消息、晚期绑定和多态性是同一件事情:早期绑定的消息只是一个过程调用,如果您不能向不同类型的对象发送相同的消息,那么为什么要晚期绑定呢?委托、封装和一切都是对象也从某种意义上继承自消息传递。 - Damien Pollet

9
基本上,面向对象编程真正的核心在于“消息传递”。
在过程式语言中,我会像这样调用一个函数:
  f(x)

在编译时,f的名称可能绑定到特定的代码块。(除非这是一种具有高阶函数或函数指针的过程性语言,但暂且忽略这种可能性。)因此,这行代码只能意味着一件明确的事情。

在面向对象的语言中,我向一个对象传递消息,可能像这样:

 o.m(x) 

在这种情况下,m不是代码块的名称,而是“方法选择器”,实际调用哪个代码块取决于对象o。这行代码更加模糊或通用,因为它在不同的情况下可能意味着不同的事情,具体取决于o。
在大多数面向对象的语言中,对象o有一个“类”,并且类确定调用哪个代码块。在一些面向对象的语言(最著名的是Javascript)中,o没有类,但在运行时直接附加了方法,或者从原型继承了方法。
我的划分是,对于语言成为面向对象语言,既不需要类也不需要继承。但这种多态处理消息的方式是必不可少的。
虽然您可以在C语言中使用函数指针来模拟此操作,但这对于将C称为面向对象语言来说是不够的,因为您将不得不实现自己的基础架构。您可以这样做,并且可以使用面向对象的风格,但语言并没有为您提供。

9

根据Booch的说法,以下元素:

  • 抽象
  • 封装
  • 模块化
  • 层次结构(继承)

次要:

  • 类型
  • 并发性
  • 持久性

6
“OO(面向对象)”并不是指语言本身,而是代码的特性。在C语言中也可以编写面向对象的代码(使用结构体,甚至函数指针成员),我曾经见过一些很好的例子(例如Quake 2/3 SDK)。同样,在C++中也可以编写过程式(非面向对象)的代码。
因此,我认为一个“面向对象语言”的标准应该是它是否支持编写高质量的面向对象代码。例如,我从不会在C中使用结构体中的函数指针成员来实现普通的成员函数,因此我会说C不是一种面向对象的语言。
(更进一步地说,有人可能会认为Python也不是面向对象的语言,因为每一步都需要强制使用self关键字,并且构造函数被称为init等等,但这是一个信仰上的讨论。)

仅仅为了追根究底,为什么没有隐式的self关键字就意味着Python不是面向对象的? - interstar
1
一种非常有趣的看待面向对象编程的方式。“重要的不是语言,而是代码…” - flamenco

3

尽管Simula经常被认为是第一种面向对象的语言,但Smalltalk通常被视为原型面向对象语言。

当前的面向对象编程语言可以根据它们从哪些语言借用最多的概念进行松散分类:

  • 类似于Smalltalk:Ruby、Objective-C
  • 类似于Simula:C++、Object Pascal、Java、C#

不要忘记Objective C和Javascript是来自Smalltalk分支的。 - Mamut

2
我很高兴与大家分享这个内容,对我来说非常有趣和有用。以下是一段摘自1994年《滚石》杂志采访的内容,斯蒂夫(不是程序员)用简单的语言解释了面向对象编程。
Jeff Goodell: 请用简单的语言解释什么是面向对象软件?
Steve Jobs: 对象就像人一样。它们是有知识内在,知道如何做事情并具有记忆的“生物”。你不需要在一个非常低层次上与它们交互,而是可以在一个非常高的抽象级别上与它们交互,就像我们现在所做的一样。
举个例子:如果我是你的洗衣物品对象,你可以把你的脏衣服给我,并发送一条消息,“你能帮我洗一下衣服吗?”我碰巧知道旧金山最好的洗衣房在哪里。我会说英语,口袋里有美元。所以我出去拦了一辆出租车,告诉司机带我去旧金山的这个地方。我去把你的衣服洗了,然后跳回出租车,回到这里。我给你你的干净衣服,说:“你的干净衣服在这里。”
你不知道我是如何做到的。你并不知道这个洗衣房在哪里,甚至可能你不会讲英语,也不会拦出租车。你不能支付车费,口袋里没有美元。但是,我知道如何操作所有的事情。而且你不需要了解任何事情。所有的复杂性都隐藏在我内部,我们能够在非常高抽象级别上进行交互。对象就是这样的。它们封装了复杂性,而对复杂性的接口则是高层次的。

1
据我所知,语言“面向对象”的主要观点是支持将数据和处理该数据的方法分组的想法,通常通过类、模块、继承、多态等实现。
请参见此讨论,了解人们对面向对象的看法。
至于“原型”面向对象语言——确实是Smalltalk,正如Kristopher所指出的那样。

0

当你可以创建类时,它就是面向对象的
例如:Java 是面向对象的,JavaScript 不是,而 C++ 看起来像某种“面向对象好奇”的语言


JavaScript通常被认为是面向对象的:它确实有对象,只是没有类。具体来说,它是基于原型的面向对象,而不是基于类的面向对象。如果需要,您可以在JavaScript的原型系统之上实现类系统,ES6和CoffeeScript通过语法糖正是这样做的。反过来也是如此,类导向的面向对象语言(如Ruby,但可能不包括Java)也可以很容易地执行原型面向对象。 - Marnen Laibow-Koser

0

简单:(比较保险字符)

1-Polymorphism 2-Inheritance 3-Encapsulation 4-Re-use. :)


0

对象:对象是数据的存储库。例如,如果MyList是一个ShoppingList对象,那么MyList可能记录你的购物清单。

类:类是一种对象类型。许多相同类的对象可能存在;例如,MyList和YourList都可以是ShoppingList对象。

方法:在对象或类上操作的过程或函数。方法与特定类相关联。例如,addItem可能是将项目添加到任何ShoppingList对象的方法。有时,方法与一组类相关联。例如,addItem可能对任何List进行操作,其中ShoppingList只是一种类型。

继承:类可以从更一般的类中继承属性。例如,ShoppingList类从List类继承存储项目序列的属性。

多态性:能够使一个方法调用适用于几个不同类的对象,即使这些类需要不同的方法实现。例如,一行代码可能能够在每种类型的List上调用“addItem”方法,即使将项目添加到ShoppingList与将项目添加到ShoppingCart完全不同。

面向对象编程:每个对象都知道它自己的类以及哪些方法可以操作该类中的对象。每个购物清单和每个购物车都知道哪个addItem实现适用于它。

在这个列表中,真正区分面向对象语言(如Java、Python)和过程式语言(如C、Fortran、Basic、Pascal)的是多态性。

来源:https://www.youtube.com/watch?v=mFPmKGIrQs4&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd


1
Fortran支持多态性。 - francescalus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接