昨晚引起了我的注意。
在最新的ALT.NET Podcast上,Scott Bellware讨论了与Ruby相对的语言,如c#,java等语言。不是真正面向对象而是选择“以类为导向”这一短语。他们用非常含糊的术语谈论这种区别,而没有详细讨论或讨论利弊。
这里有什么真正的区别,重要的是多少?那么其他什么语言是“面向对象的”?这听起来很有意思,但我不想学习Ruby只是为了知道如果我缺少什么。
更新:在阅读下面的一些答案之后,似乎人们普遍认为参考是鸭子打字。我不确定我理解的是,这最终会发生变化。特别是如果你已经做了松散耦合的正确tdd等等等等等等。有人能向我展示一个我可以用ruby做的奇妙事情的例子,我不能用c#做这个并且这例证了这种不同的oop方法吗?
答案 0 :(得分:23)
在面向对象的语言中,对象是通过定义对象而不是类来定义的,尽管类可以为给定抽象的特定cookie切割器定义提供一些有用的模板。在面向类的语言中,例如C#,对象必须由类定义,并且这些模板通常在运行时被封装和打包并变为不可变。必须在运行时之前定义对象并且对象的定义是不可变的这种任意约束不是面向对象的概念;它是面向班级的。
答案 1 :(得分:15)
这里的鸭子输入评论更多地归因于Ruby和Python比C#更像动态这一事实。它与OO Nature没有任何关系。
贝尔软件的意思是,在Ruby中,一切都是对象。即使是上课。类定义是对象的实例。因此,您可以在运行时添加/更改/删除行为。
另一个很好的例子是NULL也是一个对象。在红宝石中,一切都是一个对象。拥有如此深入的OO可以实现一些有趣的元编程技术,例如method_missing。
答案 2 :(得分:10)
从概念上讲,我认为OO design 提供了用于处理软件系统复杂性的抽象概念。该语言是实现OO设计的工具 - 有些使其比其他设计更自然。我仍然认为,从更常见和更广泛的定义来看,C#和其他仍然是面向对象的语言。
答案 3 :(得分:9)
OOP有三个支柱
如果一种语言可以做这三件事,那就是OOP语言。
我很确定语言X的论点比语言A更好地完成OOP。
答案 4 :(得分:4)
OO有时被定义为面向消息的。这个想法是方法调用(或属性访问)实际上是发送给另一个对象的消息。接收对象如何处理消息是完全封装的。通常,消息对应于随后执行的方法,但这只是一个实现细节。例如,您可以创建一个catch-all处理程序,无论消息中的方法名称如何,都会执行该处理程序。
C#中的静态OO没有这种封装。按摩具有以对应于现有方法或属性,否则编译器会抱怨。然而,Smalltalk,Ruby或Python等动态语言支持“基于消息的”OO。
所以从这个意义上来说,C#和其他静态类型的OO语言并不是真正的OO,因为缺乏“真正的”封装。
答案 5 :(得分:3)
更新:它的新浪潮......这表明我们到目前为止所做的一切都是过去的..似乎在播客和书籍中支撑了很多..也许这就是你所听到的。
到目前为止,我们一直关注静态类,而不是释放面向对象开发的力量。我们一直在做'基于班级的开发'。类是固定/静态模板以创建对象。类的所有对象都是相同的。
e.g。只是为了说明我一直在讨厌的问题......让我从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”在某种程度上就像“矩阵”......你继续在循环中继续前进。像这一个..其中Container的基类可以是一个数组或一个哈希,基于生成的随机数为0.5的那一边。
class Container < (rand < 0.5 ? Array : Hash)
end
Ruby,javascript和新旅似乎是开创这一点的人。我仍然在这一个......阅读并试图理解这一新现象。似乎是强大的...太强大了..有用吗?我需要睁大眼睛。有趣的时间..这些。
答案 6 :(得分:2)
也许他们暗指鸭子打字和类层次结构之间的区别?
如果它像鸭子一样走路,像鸭子一样嘎嘎叫,只是假装它是一只鸭子并踢它。
在C#,Java等中,编译器很多关于:你是否允许对该对象进行此操作?
面向对象与面向类可能意味着:语言是否担心对象或类?
例如:在Python中,要实现可迭代对象,您只需提供一个方法__iter__()
,该方法返回一个具有名为next()
的方法的对象。这就是它的全部内容:没有接口实现(没有这样的东西)。没有子类化。就像鸭子/迭代器一样说话。
编辑:这篇文章在我重写所有内容时被赞成。对不起,再也不会这样了。原始内容包括尽可能多地学习语言的建议,并且不必担心医生对语言的看法/说法。
答案 7 :(得分:2)
我只听了引发你问题的播客的前6-7分钟。如果他们的意图是说C#不是纯粹面向对象的语言,那实际上是正确的。 C#中的所有内容都不是对象(至少原语不是,尽管boxing会创建一个包含相同值的对象)。在Ruby中,一切都是对象。达伦和本似乎已经涵盖了他们讨论“鸭子打字”的所有基础,所以我不会重复它。
这种差异(一切物体与一切物体不是一个物体)是否具有实质性/重要性是一个我无法回答的问题,因为我没有足够的深度将Ruby与C#进行比较。那些在这里知道Smalltalk的人(我没有,虽然我希望我这样做)可能一直在寻找Ruby运动,因为它是30年前第一个纯粹的OO语言。
答案 8 :(得分:1)
这确实是一个抽象播客! 但是我看到了他们所得到的东西 - 他们只是被Ruby Sparkle迷住了。 Ruby允许你做一些基于C语言和Java程序员甚至都不会想到的东西+这些东西的组合让你实现不可思议的可能性。 向你喜欢的内置String类添加新方法,传递未命名的代码块以供其他人执行,mixins ...传统的人不习惯改变太远离类模板的对象。 它肯定是一个全新的世界。
至于C#家伙不够OO ......不要把它放在心上..当你大惊小怪的时候,把它当成你说的话。 Ruby对大多数人都这样做 如果我不得不推荐一种语言供人们在当前的十年中学习......那就是Ruby。我很高兴我做了..虽然有些人可能会声称Python。但它像我的意见..男人! :d
答案 9 :(得分:1)
我不认为这是关于鸭子打字的具体内容。例如,C#已经支持有限的鸭子类型 - 例如,您可以在实现MoveNext和Current的任何类上使用foreach。
duck-typing的概念与Java和C#等静态类型语言兼容,它基本上是反射的扩展。
静态与动态类型确实如此。两者都是正确的OO,就像有这样的东西一样。在学术界之外,真的不值得辩论。
垃圾代码可以用任何一种方式编写。伟大的代码可以写在任何一个。一个模型绝对没有任何功能,而另一个模型无法做到。
真正的区别在于编码的性质。静态类型会降低自由度,但优点是每个人都知道他们正在处理什么。实时更改实例的机会非常强大,但成本是很难知道你正在使用的是什么。
例如对于Java或C#,intellisense很容易 - IDE可以快速生成一系列可能性。对于Javascript或Ruby来说,这变得更加困难。
对于某些事情,例如生成其他人将使用的API,静态类型有一个真正的优势。对于其他人,例如快速生产原型,其优势在于动态。
值得在你的技能工具箱中理解这两者,但远不如理解你已经在真实深度使用的那个重要。
答案 10 :(得分:1)
面向对象是一个概念。这个概念基于某些想法。这些想法的技术名称(实际上是时间演变的原则,从第一个小时开始就没有出现过)已经在上面给出了,我不打算重复它们。我宁愿把它解释为尽可能简单和非技术性。
OO编程的想法是有对象。对象是小的独立实体。这些实体可能嵌入了信息,也可能没有。如果他们有这样的信息,只有实体本身可以访问或更改它。实体通过在彼此之间发送消息来彼此通信。将此与人类进行比较。人类是独立的实体,其内部数据存储在他们的大脑中并且通过通信(例如彼此交谈)彼此交互。如果你需要某人的大脑知识,你不能直接访问它,你必须问他一个问题,他可以回答你,告诉你你想知道什么。
基本上就是这样。这是OO编程背后的真实想法。编写这些实体,定义它们之间的通信并让它们一起交互以形成应用程序。这个概念不受任何语言的约束。这只是一个概念,如果你用C#,Java或Ruby编写代码,那就不重要了。通过一些额外的工作,这个概念甚至可以在纯C中完成,即使它是一种功能语言,但它提供了概念所需的一切。
不同的语言现在采用了OO编程的概念,当然概念并不总是相同的。例如,某些语言允许其他语言禁止。现在涉及的概念之一是类的概念。有些语言有类,有些则没有。类是对象的外观蓝图。它定义了一个对象的内部数据存储,它定义了一个对象可以理解的消息,如果有继承(对于OO编程来说不是必需的),那么类也定义了从哪个其他类(或者如果允许多继承,则此类继承(如果存在选择性继承,则继承哪些属性)。创建这样的蓝图后,您现在可以根据此蓝图生成无限量的对象。
但是有些OO语言没有类。然后如何构建对象?嗯,通常是动态的。例如。您可以创建一个新的空白对象,然后动态添加内部结构,如实例变量或方法(消息)。或者,您可以复制已存在的对象及其所有属性,然后对其进行修改。或者可能将两个对象合并为一个新对象。与基于类的语言不同,这些语言非常动态,因为您可以在运行时动态生成对象,即使开发人员在开始编写代码时也没有考虑过。
通常这种动态有一个代价:语言越动态,内存(RAM)对象就越浪费,一切都变得越慢,因为程序流也非常动态,如果编译器生成有效的代码很难没有机会预测代码或数据流。 JIT编译器一旦知道了程序流,就可以在运行时优化它的某些部分,但是由于这些语言是动态的,程序流可以随时改变,迫使JIT抛弃所有编译结果并重新编译相同的代码一遍又一遍。
但这是一个很小的实现细节 - 它与基本的OO原则无关。没有人说对象需要是动态的,或者必须在运行时可以改变。维基百科说得很好:
编程技术可能包括 信息隐藏等功能 数据抽象,封装, 模块性,多态性和 继承。
http://en.wikipedia.org/wiki/Object-oriented_programming
他们可能或他们可能不。这不是强制性的。强制性只是对象的存在,并且它们必须具有相互交互的方式(否则,如果它们不能相互交互,则对象将毫无用处。)
答案 11 :(得分:1)
你问道:“有人能告诉我一个我可以用红宝石做的奇妙事情的例子,我不能用c#来做这个例子,这可以说明这种不同的oop方法吗?”
一个很好的例子是活动记录,ORM内置于rails中。模型类是在运行时基于数据库模式动态构建的。
答案 12 :(得分:0)
我会捅这个。
Python和Ruby是鸭子型的。要生成这些语言中的任何可维护代码,您几乎必须使用测试驱动开发。因此,开发人员无需创建巨大的支持框架即可轻松地将依赖项注入其代码中,这一点非常重要。
成功的依赖注入取决于拥有一个非常好的对象模型。这两个是同一枚硬币的两面。如果您真的了解如何使用OOP,那么您应该默认创建可以轻松注入依赖项的设计。
因为依赖注入在动态类型语言中更容易,所以Ruby / Python开发人员觉得他们的语言比其他静态类型的同行更能理解OO的教训。
答案 13 :(得分:0)
这实际上可能归结为这些人看到别人在c#和java中所做的事情,而不是支持OOP的c#和java。大多数语言都可以用于不同的编程范例。例如,您可以用c#和scheme编写过程代码,并且可以在java中进行函数式编程。它更多地是关于你想要做什么以及语言支持什么。