是啥让语言面向对象?
Posted
技术标签:
【中文标题】是啥让语言面向对象?【英文标题】:What makes a language Object-Oriented?是什么让语言面向对象? 【发布时间】:2010-09-06 22:40:13 【问题描述】:既然没有有意义的术语的辩论是meaningless,我想我会指着房间里的大象问:究竟是什么让语言“面向对象”?我在这里寻找的不是教科书式的答案,而是基于您使用在您的领域中运行良好的 OO 语言的经验,无论它可能是什么。
一个可能有助于首先回答的相关问题是:面向对象语言的原型是什么?为什么?
【问题讨论】:
【参考方案1】:Definitions for Object-Orientation 当然是huge can of worms,但这是我的 2 美分:
对我来说,面向对象就是通过发送消息进行协作的对象。对我来说,这就是面向对象语言的一个最重要的特征。
如果我必须列出面向对象语言必须具备的所有特性的有序列表,它应该是这样的:
-
Objects sending messages to other objects
一切都是对象
Late Binding
Subtype Polymorphism
继承或类似的表达方式,如Delegation
Encapsulation
Information Hiding
抽象
显然,这个列表是非常有争议的,因为它排除了许多被广泛认为是面向对象的语言,例如Java、C#和C++,所有这些都违反了第1、2点和 3. 然而,毫无疑问,这些语言允许面向对象编程(但 C 也是如此)甚至促进它(C 没有)。因此,我开始将满足这些要求的语言称为“纯面向对象”。
作为典型的面向对象语言,我将命名为 Self 和 Newspeak。
两者都满足上述要求。两者都受到Smalltalk 的启发和继任者,并且在某种意义上实际上都设法成为“更多的OO”。我喜欢 Self 和 Newspeak 的地方在于,它们都将消息发送范式发挥到了极致(Newspeak 甚至比 Self 更甚)。
在新话中,一切都是消息发送。没有实例变量,没有字段,没有属性,没有常量,没有类名。它们都是通过使用 getter 和 setter 来模拟的。
在 Self 中,没有类,只有对象。这强调了 OO 真正是关于:对象,而不是类。
【讨论】:
消息、后期绑定和多态是一回事:早期绑定的消息只是一个过程调用,如果不能将相同的消息发送给不同类型的对象,那为什么要迟到绑定?委托、封装和一切都是对象,在某种程度上也源自消息传递。【参考方案2】:根据 Booch,以下元素: 专业:
抽象 封装 模块化 层次结构(继承)次要:
打字 并发 坚持【讨论】:
【参考方案3】:基本上面向对象真的归结为“消息传递”
在程序语言中,我这样调用函数:
f(x)
并且名称 f 可能在编译时绑定到特定的代码块。 (除非这是一种具有高阶函数或函数指针的过程语言,但让我们暂时忽略这种可能性。)所以这行代码只能意味着一个明确的事情。
在面向对象的语言中,我将消息传递给对象,可能是这样的:
o.m(x)
在这种情况下。 m 不是代码块的名称,而是“方法选择器”,调用哪个代码块实际上在某种程度上取决于对象 o。这行代码更加模棱两可或更笼统,因为它在不同的情况下可能意味着不同的东西,具体取决于o。
在大多数 OO 语言中,对象 o 有一个“类”,该类决定调用哪个代码块。在一些 OO 语言(最著名的是 javascript)中,o 没有类,但在运行时直接附加了方法,或者从原型继承了它们。
我的分界是类和继承都不是面向对象的语言所必需的。但是这种消息的多态处理是必不可少的。
虽然你可以用 C 中的函数指针来伪造它,但这还不足以让 C 被称为 OO 语言,因为你必须实现自己的基础架构。你可以这样做,OO 风格是可能的,但语言没有给你它。
【讨论】:
【参考方案4】:OO 并不是真正的语言,而是代码。
可以编写面向对象的 C 代码(如果您愿意,可以使用结构甚至函数指针成员),我已经看到了一些很好的例子。 (想到 Quake 2/3 SDK。)当然也可以用 C++ 编写过程(即非 OO)代码。
考虑到这一点,我想说是该语言对编写良好的 OO 代码的支持使其成为“面向对象的语言”。我永远不会为在 C 中的结构中使用函数指针成员而烦恼,例如,对于普通的成员函数;所以我会说C不是面向对象的语言。
(对此进行扩展,可以说 Python 也不是面向对象的,在每一步都有强制性的“自我”引用和称为 init 的构造函数,诸如此类;但这是一个宗教讨论。 )
【讨论】:
只是上钩,为什么没有隐含的self关键字意味着python不是OO? 一种非常有趣的方式来看待 OOP。 “不是语言而是代码……”【参考方案5】:Smalltalk 通常被认为是原型 OO 语言,尽管 Simula 经常被引用为第一个 OO 语言。
当前的 OO 语言可以根据它们借用的概念最多的语言大致分类:
Smalltalk-like:Ruby、Objective-C 类仿真:C++、Object Pascal、Java、C#【讨论】:
不要忘记 Objective C 和 Javascript 来自 Smalltalk 分支【参考方案6】:我很高兴与你们分享这个,这对我来说很有趣也很有帮助。这是 1994 年滚石采访的摘录,史蒂夫(不是程序员)在采访中用简单的术语解释了 OOP。
Jeff Goodell:您能简单地解释一下什么是面向对象的软件吗?
史蒂夫·乔布斯:物体就像人。他们是活生生的,呼吸着东西,里面有关于如何做事的知识,里面有记忆,所以他们可以记住事情。与其在非常低的层次上与它们交互,不如在非常高的抽象层次上与它们交互,就像我们在这里所做的那样。
举个例子:如果我是你的洗衣对象,你可以把你的脏衣服给我,然后给我发一条消息,上面写着:“请帮我洗衣服。”我碰巧知道旧金山最好的洗衣店在哪里。我会说英语,口袋里有美元。所以我出去叫了一辆出租车,告诉司机带我去旧金山的这个地方。我去洗你的衣服,我跳回驾驶室,我回到这里。我给你干净的衣服,然后说:“这是你的干净衣服。”
你不知道我是怎么做到的。你对洗衣房一无所知。也许你会说法语,你甚至不能叫出租车。你买不起,你的口袋里没有美元。然而,我知道如何做到这一切。而且你不必知道任何事情。所有这些复杂性都隐藏在我的内心,我们能够以非常高的抽象层次进行交互。这就是对象。它们封装了复杂性,并且对这种复杂性的接口是高级别的。
【讨论】:
【参考方案7】:据我所知,什么使语言“面向对象”的主要观点是支持对数据进行分组的想法,以及对这些数据起作用的方法,这通常通过类、模块、继承、多态性来实现等。
请参阅this discussion,了解人们的想法(想法?)面向对象意味着什么的概述。
至于“原型”OO 语言 - 正如 Kristopher 所指出的,这确实是 Smalltalk。
【讨论】:
【参考方案8】:支持类、方法、属性、封装、数据隐藏、继承、多态、抽象...?
【讨论】:
【参考方案9】:不管理论上的含义,它似乎是
“任何有‘class’关键字的语言”:-P
【讨论】:
【参考方案10】:为了进一步说明 aib 所说的,我想说一种语言并不是真正的面向对象的,除非可用的标准库是面向对象的。最大的例子是 php。尽管它支持所有标准的面向对象概念,但如此大比例的标准库不是面向对象的事实意味着几乎不可能以面向对象的方式编写代码。
如果所有标准库仍然要求您在所有函数调用前加上 mysql_ 和 pgsql_ 之类的东西,那么它们是否引入命名空间并不重要,当使用在实际 API 中支持命名空间的语言时,您可以摆脱带有 mysql_ 的函数,并且在文件顶部只有一个简单的“include system.db.mysql.*”,以便它知道这些东西的来源。
【讨论】:
【参考方案11】:当你可以创建类时,它是面向对象的 例如:java 是面向对象的,javascript 不是,而 c++ 看起来像是某种“对象好奇”的语言
【讨论】:
JavaScript 通常被认为是面向对象的:它确实 有对象,只是没有类。 (具体来说,它是基于原型的 OO,而不是基于类的 OO。)如果您愿意,您实际上可以在 JavaScript 中的原型系统之上实现一个类系统,而 ES6 和 CoffeeScript 都通过语法糖来做到这一点。反过来也是如此,顺便说一句:一些面向类的 OO 语言(如 Ruby,但可能不是 Java)可以轻松实现原型 OO。【参考方案12】:根据我的经验,语言不是面向对象的,代码是。
几年前,当我开始深入了解 OO 时,我正在用 AppleScript 编写一套程序,这些程序并没有真正执行任何面向对象的功能。在 AppleScript 中编写对象很笨拙,尽管如果您花时间弄清楚如何创建类、构造函数等是可能的。
该语言是该领域的正确语言:让 Macintosh 上的不同程序协同工作,以根据输入文件完成一些自动任务。不厌其烦地自我实施面向对象的风格是正确的编程选择,因为它使代码更容易排除故障、测试和理解。
在将代码从过程代码转换为 OO 时,我注意到的最重要的特性是封装:属性和方法调用。
【讨论】:
【参考方案13】:简单:(比较保险字符)
1-多态性 2-继承 3-封装 4-重复使用。 :)
【讨论】:
【参考方案14】:对象:对象是数据的存储库。例如,如果 MyList 是 ShoppingList 对象,MyList 可能会记录您的购物清单。
类:类是对象的一种类型。可能存在许多同一类的对象;例如,MyList 和 YourList 可能都是 ShoppingList 对象。
方法:对对象或类进行操作的过程或函数。方法与特定的类相关联。例如,addItem 可能是一种将项目添加到任何 ShoppingList 对象的方法。有时,一个方法与一系列类相关联。例如,addItem 可以对任何 List 进行操作,而 ShoppingList 只是其中一种类型。
继承:一个类可以从更通用的类继承属性。例如,ShoppingList 类从 List 类继承了存储项目序列的属性。
多态性:让一个方法调用作用于几个不同类的对象的能力,即使这些类需要方法调用的不同实现。例如,即使向 ShoppingList 添加商品与向 ShoppingCart 添加商品完全不同,一行代码也可能对每种 List 调用“addItem”方法。
面向对象:每个对象都知道自己的类以及哪些方法操作该类中的对象。每个 ShoppingList 和每个 ShoppingCart 都知道 addItem 的哪个实现适用于它。
在这个列表中,真正将面向对象语言与过程语言(C、Fortran、Basic、Pascal)区分开来的一件事是多态性。
来源:https://www.youtube.com/watch?v=mFPmKGIrQs4&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd
【讨论】:
Fortran 支持多态性。【参考方案15】:如果一种语言被设计为具有专门支持面向对象编程的工具(4 个特性),那么它就是一种面向对象的编程语言。
您可以使用或多或少的任何语言以面向对象的风格进行编程。面向对象的是代码而不是语言。
真正的面向对象语言的示例有 Java、c#、Python、Ruby、C++。 此外,还可以通过扩展来提供面向对象的功能,例如 PHP、Perl 等。
您可以使用 C 编写面向对象的代码,但它不是面向对象的程序。朗。它不是为此而设计的(这就是 C++ 的全部意义所在)
【讨论】:
【参考方案16】:原型
用代码表达真实世界场景的能力。
foreach(House house in location.Houses)
foreach(Deliverable mail in new Mailbag(new Deliverable[]
GetLetters(),
GetPackages(),
GetAdvertisingJunk()
)
if(mail.AddressedTo(house))
house.Deliver(mail);
-
foreach(Deliverable myMail in GetMail())
IReadable readable = myMail as IReadable;
if ( readable != null )
Console.WriteLine(readable.Text);
为什么?
帮助我们更容易理解这一点。它在我们的头脑中更有意义,如果实施得当,代码会更高效、可重用并减少重复。
要实现这一点,您需要:
指针/引用以确保 this == this 和 this != that。 类指向(例如 Arm)存储数据(int hairyness)和操作(Throw(IThrowable)) 多态(继承和/或接口)以通用方式处理特定对象,以便您可以阅读书籍以及在墙上涂鸦(均实现 IReadable) 封装,因为苹果不公开 Atoms[] 属性【讨论】:
以上是关于是啥让语言面向对象?的主要内容,如果未能解决你的问题,请参考以下文章