15

昨晚引起了我的注意。

在最新的ALT.NET 播客中,Scott Bellware 讨论了与 Ruby 相比,c#、java 等语言如何。并不是真正的面向对象,而是选择“面向类”这个短语。他们用非常模糊的术语谈论这种区别,而没有深入细节或讨论利弊。

这里的真正区别是什么?它有多大关系?那么还有哪些其他语言是“面向对象的”?这听起来很有趣,但我不想学习 Ruby 只是为了知道我缺少什么。

更新:阅读下面的一些答案后,似乎人们普遍同意该参考是鸭式打字。我不确定我是否仍然理解的是,这最终会改变一切的说法。特别是如果你已经在做适当的 tdd 松耦合等等等等。有人可以向我展示一个我可以用 ruby​​ 做的奇妙事情的例子,而我不能用 c# 做这件事,并举例说明了这种不同的 oop 方法吗?

4

14 回答 14

23

在面向对象的语言中,对象是通过定义对象而不是类来定义的,尽管类可以为给定抽象的特定、千篇一律的定义提供一些有用的模板。在面向类的语言中,例如 C#,对象必须由类定义,并且这些模板通常在运行前被封装和打包并使其不可变。对象必须在运行时之前定义并且对象的定义是不可变的这种任意约束不是面向对象的概念;它是面向班级的。

于 2009-04-27T09:12:11.753 回答
15

此处的鸭子类型注释更多地归因于 Ruby 和 Python比 C#更动态的事实。它与OO Nature 没有任何关系。

(我认为)Bellware 的意思是,在 Ruby 中,一切都是对象。甚至一堂课。类定义是对象的一个​​实例。因此,您可以在运行时向其添加/更改/删除行为。

另一个很好的例子是 NULL 也是一个对象。在 ruby​​ 中,一切都是一个对象。在整个存在中拥有如此深入的 OO 允许一些有趣的元编程技术,例如 method_missing。

于 2008-09-09T15:19:32.663 回答
10

IMO,它确实过度定义了“面向对象”,但他们所指的是 Ruby 与 C#、C++、Java 等不同,它没有使用定义类——你真的只能直接使用对象. 相反,例如在 C# 中,您定义,然后必须通过 new 关键字将其实例化为对象。关键是您必须在 C# 中声明一个类或对其进行描述。此外,在 Ruby 中,一切——例如偶数——都是对象。相比之下,C#仍然保留了对象类型和值类型的概念。事实上,我认为这说明了他们对 C# 和其他类似语言的看法——对象类型和值type意味着一个类型系统,这意味着您拥有一个描述类型的完整系统,而不仅仅是使用对象。

从概念上讲,我认为 OO设计提供了当今用于处理软件系统复杂性的抽象。该语言是一种用于实现 OO 设计的工具——有些使它比其他的更自然。我仍然认为,从更常见和更广泛的定义来看,C# 和其他语言仍然是面向对象的语言。

于 2008-09-09T15:20:03.083 回答
9

OOP 的三大支柱

  1. 封装
  2. 遗产
  3. 多态性

如果一种语言可以做这三件事,那么它就是一种 OOP 语言。

我很确定语言 X 的论点比语言 A 更好地进行 OOP 将永远持续下去。

于 2008-09-09T15:16:47.847 回答
4

OO 有时被定义为面向消息的。这个想法是方法调用(或属性访问)实际上是发送给另一个对象的消息。接收对象如何处理消息是完全封装的。通常,消息对应于随后执行的方法,但这只是一个实现细节。例如,您可以创建一个包罗万象的处理程序,无论消息中的方法名称如何,该处理程序都会执行。

像 C# 中的静态 OO 没有这种封装。按摩必须对应于现有的方法或属性,否则编译器会抱怨。然而,像 Smalltalk、Ruby 或 Python 这样的动态语言确实支持“基于消息的”OO。

所以从这个意义上说,C# 和其他静态类型的 OO 语言不是真正的 OO,因为它们缺乏“真正的”封装。

于 2008-10-17T12:28:46.033 回答
3

更新:它是新浪潮……这表明我们到目前为止所做的一切都已经过去了……似乎在播客和书籍中得到了很大的支持……也许这就是你所听到的。

到目前为止,我们一直关注静态类,并没有释放出面向对象开发的力量。我们一直在做“基于类的开发”。类是用于创建对象的固定/静态模板。一个类的所有对象都是平等的。

例如,为了说明我一直在喋喋不休...让我从我刚刚有幸观看的 PragProg 截屏视频中借用一段 Ruby 代码片段。“基于原型的开发”模糊了对象和类之间的界限。没有区别。

animal = Object.new                  # create a new instance of base Object

def animal.number_of_feet=(feet)     # adding new methods to an Object instance. What?
  @number_of_feet = feet
end
def animal.number_of_feet
  @number_of_feet
end

cat = animal.clone          #inherits 'number_of_feet' behavior from animal
cat.number_of_feet = 4

felix = cat.clone           #inherits state of '4' and behavior from cat
puts felix.number_of_feet   # outputs 4

这个想法是它比传统的基于类的继承更强大的继承状态和行为的方式。它在某些“特殊”场景(我尚未理解)中为您提供了更大的灵活性和控制力。这允许诸如 Mix-ins 之类的东西(重新使用没有类继承的行为)..

通过挑战我们如何思考问题的基本原语,“真正的 OOP”在某种程度上就像“矩阵”......你继续在循环中进行 WTF。就像这个.. Container 的基类可以是 Array 或 Hash,取决于生成的随机数是 0.5 的哪一侧。

class Container < (rand < 0.5 ? Array : Hash)
end

Ruby、javascript 和新的旅似乎是这方面的先驱。我还在研究这个……阅读并试图理解这种新现象。似乎很强大..太强大了..有用吗?我需要睁大眼睛。有趣的时间..这些。

于 2008-09-18T15:07:22.537 回答
2

也许他们在暗示鸭子类型和类层次结构之间的区别?

如果它像鸭子一样走路和像鸭子一样嘎嘎叫,就假装它是鸭子并踢它。

在 C#、Java 等中,编译器会大惊小怪:你是否允许对那个对象执行此操作?

因此,面向对象与面向类可能意味着:语言是否担心对象或类?

例如:在 Python 中,要实现一个可迭代对象,您只需要提供一个方法,该方法__iter__()返回一个具有名为 的方法的对象next()。这就是它的全部内容:没有接口实现(没有这样的东西)。没有子类化。就像鸭子/迭代器一样说话。

编辑:当我重写所有内容时,这篇文章被投了赞成票。对不起,以后再也不会这样做了。原始内容包括建议学习尽可能多的语言,并且不必担心语言医生对语言的想法/说法。

于 2008-09-09T15:07:09.650 回答
2

我只听了引发您问题的播客的前 6-7 分钟。如果他们的意图是说 C# 不是纯粹的面向对象语言,那实际上是正确的。C# 中的一切都不是对象(至少原语不是,尽管装箱创建了一个包含相同值的对象)。在 Ruby 中,一切都是对象。Daren 和 Ben 在他们关于“duck-typing”的讨论中似乎涵盖了所有基础,所以我不再重复。

这种差异(所有对象与所有非对象)是否重要/重要是我无法轻易回答的问题,因为我没有足够的 Ruby 深度来将其与 C# 进行比较。那些知道 Smalltalk 的人(我不知道,虽然我希望我知道)可能一直在以某种乐趣看待 Ruby 运动,因为它是 30 年前第一个纯 OO 语言。

于 2008-09-09T15:32:58.557 回答
1

那确实是一个抽象的播客!
但我明白他们在说什么——他们只是被 Ruby Sparkle 弄得眼花缭乱。Ruby 允许您做基于 C 和 Java 的程序员甚至不会想到的事情 + 这些事情的组合让您实现梦想不到的可能性。向内置的 String 类添加新方法,因为您喜欢它,传递未命名的代码块供其他人执行,mixins... 传统的人不习惯对象更改与类模板太远。它肯定是一个全新的世界。

至于 C# 的人还不够 OO……别把它放在心上……当你大吃一惊的时候,把它当作你说的话。Ruby 对大多数人都是这样做的。
如果我必须推荐一种语言供人们在当前十年学习......它会是 Ruby。我很高兴我做到了.. 虽然有些人可能会声称 Python。但它就像我的意见.. 伙计!:D

于 2008-09-09T15:53:29.693 回答
1

我不认为这与鸭子打字有关。例如,C# 已经支持有限的鸭子类型 - 例如,您可以在任何实现 MoveNext 和 Current 的类上使用 foreach。

鸭子类型的概念与 Java 和 C# 等静态类型语言兼容,它基本上是反射的扩展。

这确实是静态与动态类型的情况。两者都是正确的-OO,只要有这样的事情。在学术界之外,这真的不值得争论。

垃圾代码都可以写。伟大的代码可以写在任何一个。绝对没有任何功能是一种模型可以做到的,而另一种则不能。

真正的区别在于所完成编码的性质。静态类型降低了自由度,但优点是每个人都知道他们在处理什么。动态更改实例的机会非常强大,但代价是很难知道您在处理什么。

例如,对于 Java 或 C#,智能感知很容易 - IDE 可以快速生成可能性的下拉列表。对于 Javascript 或 Ruby,这变得更加困难。

对于某些事情,例如生成一个其他人将使用的 API,静态类型具有真正的优势。对于其他人,例如快速生产原型,优势在于动态。

值得在您的技能工具箱中了解两者,但远不如了解您已经真正深入使用的工具箱重要。

于 2008-10-17T12:09:48.570 回答
1

面向对象是一个概念。这个概念是基于某些想法。这些想法的技术名称(实际上是随着时间的推移而发展起来的原则,从一开始就没有出现)上面已经给出了,我不会重复它们。我宁愿尽可能简单和非技术性地解释这一点。

OO 编程的思想是有对象。对象是小的独立实体。这些实体可能有嵌入信息,也可能没有。如果他们拥有此类信息,则只有实体本身可以访问或更改它。实体通过在彼此之间发送消息来相互通信。将此与人类进行比较。人类是独立的实体,内部数据存储在他们的大脑中,并通过交流(例如相互交谈)相互交互。如果你需要来自别人大脑的知识,你不能直接访问它,你必须问他一个问题,他可能会回答你,告诉你你想知道什么。

基本上就是这样。这是OO编程背后的真正想法。编写这些实体,定义它们之间的通信并让它们交互在一起以形成一个应用程序。这个概念不受任何语言的约束。这只是一个概念,如果您使用 C#、Java 或 Ruby 编写代码,这并不重要。通过一些额外的工作,这个概念甚至可以在纯 C 中完成,即使它是一种函数式语言,但它提供了该概念所需的一切。

现在不同的语言都采用了这种面向对象编程的概念,当然这些概念并不总是相同的。例如,某些语言允许其他语言禁止的内容。现在涉及的概念之一是类的概念。有些语言有类,有些则没有。类是对象外观的蓝图。它定义了对象的内部数据存储,定义了对象可以理解的消息以及是否存在继承(这对于 OO 编程不是强制性的!),类还定义了来自哪个其他类(或者如果允许多重继承,则为类)此类继承(如果存在选择性继承,则继承哪些属性)。一旦您创建了这样的蓝图,您现在可以根据该蓝图生成无限数量的对象。

但是,有些面向对象语言没有类。那么对象是如何构建的呢?好吧,通常是动态的。例如,您可以创建一个新的空白对象,然后向其动态添加内部结构,如实例变量或方法(消息)。或者您可以复制已经存在的对象及其所有属性,然后对其进行修改。或者可能将两个对象合并为一个新对象。与基于类的语言不同,这些语言是非常动态的,因为您可以在运行时动态生成对象,甚至开发人员在开始编写代码时都没有想到。

通常这种动态是有代价的:语言越动态,内存(RAM)对象将浪费的越多,一切变得越慢,因为程序流程也非常动态,如果编译器没有机会,编译器就很难生成有效的代码预测代码或数据流。JIT 编译器可以在运行时优化其中的某些部分,一旦他们知道程序流程,但是由于这些语言是如此动态,程序流程可以随时更改,迫使 JIT 丢弃所有编译结果并重新编译相同的代码一遍又一遍地。

但这是一个很小的实现细节——它与基本的 OO 原则无关。没有地方说对象必须是动态的或在运行时必须是可更改的。维基百科说得很好:

编程技术可能包括信息隐藏、数据抽象、封装、模块化、多态性和继承等特性。

http://en.wikipedia.org/wiki/Object-oriented_programming

他们可能会可能不会。这一切都不是强制性的。强制性的只是对象的存在,并且它们必须有相互交互的方式(否则如果它们不能相互交互,对象将毫无用处)。

于 2009-06-17T14:42:17.877 回答
1

你问:“谁能给我展示一个我可以用 ruby​​ 做的奇妙事情的例子,而我不能用 c# 做,并举例说明了这种不同的 oop 方法?”

一个很好的例子是活动记录,即内置于 Rails 中的 ORM。模型类是在运行时根据数据库模式动态构建的。

于 2010-07-12T01:56:02.397 回答
0

我会试一试。

Python 和 Ruby 是鸭式的。要使用这些语言生成任何可维护的代码,您几乎必须使用测试驱动开发。因此,对于开发人员而言,无需创建庞大的支持框架即可轻松地将依赖项注入其代码中非常重要。

成功的依赖注入取决于拥有一个非常好的对象模型。两者是同一枚硬币的两个面。如果您真的了解如何使用 OOP,那么您应该默认创建可以轻松注入依赖项的设计。

因为依赖注入在动态类型语言中更容易,Ruby/Python 开发人员觉得他们的语言比其他静态类型语言更能理解 OO 的教训。

于 2008-09-09T15:13:00.837 回答
0

这真的很可能归结为这些人看到其他人在 c# 和 java 中所做的事情,而不是 c# 和 java 支持 OOP。大多数语言可以用于不同的编程范例。例如,您可以使用 c# 和 scheme 编写过程代码,您可以使用 java 进行函数式编程。它更多的是关于你想要做什么以及语言支持什么。

于 2008-09-09T15:23:22.043 回答