由于没有有意义的术语的辩论是没有意义的,我想我会指着房间里的大象问:究竟是什么让一种语言“面向对象”?我在这里寻找的不是教科书答案,而是基于您对在您的领域中运行良好的 OO 语言的经验,无论它可能是什么。
一个可能有助于首先回答的相关问题是:面向对象语言的原型是什么,为什么?
由于没有有意义的术语的辩论是没有意义的,我想我会指着房间里的大象问:究竟是什么让一种语言“面向对象”?我在这里寻找的不是教科书答案,而是基于您对在您的领域中运行良好的 OO 语言的经验,无论它可能是什么。
一个可能有助于首先回答的相关问题是:面向对象语言的原型是什么,为什么?
对我来说,面向对象就是通过发送消息进行协作的对象。对我来说,这就是面向对象语言的一个最重要的特征。
如果我必须列出面向对象语言必须具备的所有特性的有序列表,它看起来像这样:
显然,这个列表是非常有争议的,因为它排除了被广泛认为是面向对象的各种语言,如Java、C#和C++,它们都违反了第 1、2 和 3 点。但是,毫无疑问这些语言允许面向对象编程(但C也是如此)甚至促进它(C 没有)。因此,我开始将满足这些要求的语言称为“纯面向对象”。
作为典型的面向对象语言,我将其命名为Self和Newspeak。
两者都满足上述要求。两者都受到Smalltalk的启发和继任者,并且在某种意义上实际上都设法成为“更多 OO”。我喜欢 Self 和 Newspeak 的地方在于,它们都将信息发送范式发挥到了极致(Newspeak 甚至比 Self 更甚)。
在新话中,一切都是信息发送。没有实例变量,没有字段,没有属性,没有常量,没有类名。它们都是通过使用 getter 和 setter 来模拟的。
在 Self 中,没有类,只有对象。这强调了面向对象的真正含义:对象,而不是类。
根据 Booch,以下要素: 主要:
次要的:
基本上面向对象真的归结为“消息传递”
在过程语言中,我调用这样的函数:
f(x)
并且名称 f 可能在编译时绑定到特定的代码块。(除非这是一种具有高阶函数或函数指针的过程语言,但让我们暂时忽略这种可能性。)所以这行代码只能表示一个明确的事情。
在面向对象的语言中,我将消息传递给对象,可能是这样的:
o.m(x)
在这种情况下。m 不是代码块的名称,而是“方法选择器”,调用哪个代码块实际上取决于对象 o 在某种程度上。这行代码更加模棱两可或更笼统,因为它在不同的情况下可能意味着不同的东西,具体取决于 o。
在大多数 OO 语言中,对象 o 有一个“类”,该类决定调用哪个代码块。在一些 OO 语言(最著名的是 Javascript)中,o 没有类,但在运行时直接附加了方法,或者从原型继承了它们。
我的分界是类和继承都不是面向对象的语言所必需的。但是这种消息的多态处理是必不可少的。
尽管您可以使用 C 中的函数指针来伪造这一点,但这不足以让 C 被称为 OO 语言,因为您将不得不实现自己的基础架构。你可以这样做,OO 风格是可能的,但是语言没有给你它。
面向对象的并不是真正的语言,而是代码。
可以编写面向对象的 C 代码(如果您愿意,可以使用结构甚至函数指针成员),我已经看到了一些很好的例子。(想到 Quake 2/3 SDK。)当然也可以用 C++ 编写过程(即非 OO)代码。
鉴于此,我会说这是该语言对编写良好的 OO 代码的支持,使其成为“面向对象的语言”。我永远不会为在 C 中的结构中使用函数指针成员而烦恼,例如,对于普通的成员函数;因此我会说 C 不是面向对象的语言。
(对此进行扩展,可以说 Python 也不是面向对象的,在每一步都有强制性的“自我”引用和称为init的构造函数,等等;但这是一个宗教讨论。)
Smalltalk 通常被认为是原型 OO 语言,尽管 Simula 经常被引用为第一个 OO 语言。
当前的 OO 语言可以根据它们借用最多概念的语言进行粗略分类:
我很高兴与你们分享这个,这对我来说非常有趣和有帮助。这是 1994 年滚石采访的摘录,史蒂夫(不是程序员)在采访中简单地解释了 OOP。
Jeff Goodell:您能简单地解释一下什么是面向对象的软件吗?
史蒂夫乔布斯:物体就像人。他们是活生生的,呼吸着东西,里面有关于如何做事的知识,里面有记忆,所以他们可以记住事情。而不是在非常低的层次上与它们交互,而是在非常高的抽象层次上与它们交互,就像我们在这里所做的那样。
举个例子:如果我是你的洗衣对象,你可以把你的脏衣服给我,然后给我发一条消息,上面写着:“请帮我洗衣服。” 我碰巧知道旧金山最好的洗衣店在哪里。我会说英语,口袋里有美元。所以我出去叫了一辆出租车,告诉司机带我去旧金山的这个地方。我去洗你的衣服,我跳回驾驶室,我回到这里。我给你干净的衣服,然后说:“这是你的干净衣服。”</p>
你不知道我是怎么做到的。你对洗衣房一无所知。也许你会说法语,你甚至不能叫出租车。你买不起,你的口袋里没有美元。然而,我知道如何做到这一切。你不必知道任何事情。所有这些复杂性都隐藏在我的内心,我们能够以非常高的抽象层次进行交互。这就是对象。它们封装了复杂性,并且该复杂性的接口是高级别的。
据我所知,使语言“面向对象”的主要观点是支持对数据进行分组的想法,以及对这些数据起作用的方法,这通常是通过类、模块、继承、多态性等来实现的。
有关人们认为(认为?)面向对象意味着什么的概述,请参阅此讨论。
至于“原型”OO 语言——这确实是 Smalltalk,正如 Kristopher 指出的那样。
支持类、方法、属性、封装、数据隐藏、继承、多态、抽象……?
抛开理论上的影响,似乎
“任何具有名为‘class’的关键字的语言”:-P
为了进一步说明 aib 所说的,我想说一种语言不是真正面向对象的,除非可用的标准库是面向对象的。最大的例子是 PHP。尽管它支持所有标准的面向对象概念,但如此大比例的标准库不是面向对象的事实意味着几乎不可能以面向对象的方式编写代码。
如果所有标准库仍然要求您使用 mysql_ 和 pgsql_ 之类的东西作为所有函数调用的前缀,那么它们是否引入命名空间并不重要,当使用在实际 API 中支持命名空间的语言时,您可以使用mysql_ 并且在文件顶部只有一个简单的“include system.db.mysql.*”,这样它就会知道这些东西的来源。
当你可以创建类时,它是面向对象的
,例如:java 是面向对象的,javascript 不是,c++ 看起来像是某种“对象好奇”的语言
以我的经验,语言不是面向对象的,代码是。
几年前,当我开始深入了解 OO 时,我正在用 AppleScript 编写一套程序,这些程序并没有真正实施任何面向对象的功能。用 AppleScript 编写对象很笨拙,尽管如果您花时间弄清楚如何创建类、构造函数等是可能的。
该语言是该领域的正确语言:让 Macintosh 上的不同程序协同工作,以根据输入文件完成一些自动任务。不厌其烦地自我实施面向对象的风格是正确的编程选择,因为它使代码更容易排除故障、测试和理解。
在将代码从过程转换为 OO 时,我注意到最多的特性是封装:属性和方法调用。
简单:(比较保险性质)
1-多态性 2-继承 3-封装 4-重用。:)
对象:对象是数据的存储库。例如,如果 MyList 是 ShoppingList 对象,MyList 可能会记录您的购物清单。
类:类是对象的一种类型。可能存在许多同一类的对象;例如,MyList 和 YourList 可能都是 ShoppingList 对象。
方法:对对象或类进行操作的过程或函数。方法与特定的类相关联。例如,addItem 可能是一种将项目添加到任何 ShoppingList 对象的方法。有时,一个方法与一系列类相关联。例如,addItem 可以对任何 List 进行操作,ShoppingList 只是其中的一种类型。
继承:一个类可以从一个更通用的类继承属性。例如,ShoppingList 类从 List 类继承了存储项目序列的属性。
多态性:让一个方法调用作用于几个不同的对象类的能力,即使这些类需要方法调用的不同实现。例如,一行代码可能能够对每种 List 调用“addItem”方法,即使将商品添加到 ShoppingList 与将商品添加到 ShoppingCart 完全不同。
面向对象:每个对象都知道自己的类以及哪些方法操作该类中的对象。每个 ShoppingList 和每个 ShoppingCart 都知道 addItem 的哪个实现适用于它。
在这个列表中,真正将面向对象语言与过程语言(C、Fortran、Basic、Pascal)区分开来的一件事是多态性。
资料来源:https ://www.youtube.com/watch?v=mFPmKGIrQs4&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd
如果一种语言被设计为具有专门支持面向对象编程的设施(4 个特性),那么它就是一种面向对象的编程语言。
您可以使用或多或少的任何语言以面向对象的风格进行编程。这是面向对象的代码而不是语言。
真正的面向对象语言的例子有 Java、c#、Python、Ruby、C++。此外,还可以扩展以提供面向对象的功能,如 PHP、Perl 等。
您可以使用 C 编写面向对象的代码,但它不是面向对象的 prog。朗。它不是为此而设计的(这就是 C++ 的重点)
原型
用代码表达真实世界场景的能力。
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);
}
}
为什么?
帮助我们更容易理解这一点。它在我们的脑海中更有意义,如果正确实施,代码会更高效、可重用并减少重复。
为此,您需要: