为什么声称C#人员没有进行面向对象的编程? (相对于面向类)
昨晚这引起了我的注意。
在最新的ALT.NET播客中,Scott Bellware讨论了与Ruby相反的c#,java等语言。不是真正的面向对象,而是选择短语"面向类"。他们用非常含糊的措辞谈论这种区别,而没有详细介绍或者讨论利弊。
真正的区别是什么?有什么关系?那么"面向对象"还有哪些其他语言?听起来很有趣,但我不想只学习Ruby就知道我是否缺少什么。
更新:阅读以下一些答案后,似乎人们通常同意该参考是鸭式打字。我不确定我是否仍然理解的是,这最终会改变很多。尤其是如果我们已经使用松散耦合等等进行了适当的tdd等等。有人可以给我展示一个我可以用红宝石做的奇妙事情的例子,而我用坎德做不到的例子可以证明这种不同的oop方法吗?
解决方案
回答
也许他们在暗示鸭子类型和类层次结构之间的区别?
如果它走路像鸭子,却像鸭子一样嘎嘎叫,就假装它是鸭子,踢它。
在C#,Java等中,编译器大惊小怪:是否允许在该对象上执行此操作?
因此,面向对象与面向类可能意味着:语言是否担心对象或者类?
例如:在Python中,要实现一个可迭代的对象,我们只需提供一种方法__iter __()即可返回一个对象,该对象具有一个名为next()的方法。这就是全部:没有接口实现(没有这样的东西)。没有子类。就像鸭子/迭代器一样说话。
编辑:我改写所有内容时都发表了这篇文章。抱歉,永远不会再这样做了。原始内容包括建议,以学习尽可能多的语言,并且不必担心语言医生对语言的看法/看法。
回答
我会为此刺一针。
Python和Ruby是鸭子类型的。要生成这些语言的任何可维护代码,我们几乎必须使用测试驱动的开发。因此,对于开发人员而言,轻松地将依赖项注入其代码而不必创建庞大的支持框架非常重要。
成功的依赖关系注入取决于拥有一个很好的对象模型。两者是同一枚硬币的两个侧面。如果我们真的了解如何使用OOP,则默认情况下应该创建可以轻松注入依赖项的设计。
因为依赖注入在动态类型的语言中更容易,所以Ruby / Python开发人员觉得他们的语言比其他静态类型的对语言的理解要好得多。
回答
OOP有三大支柱
- 封装形式
- 遗产
- 多态性
如果一种语言可以做到这三件事,那就是一种OOP语言。
我敢肯定,语言X的论点会比语言A做得更好,那么OOP将会永远存在。
回答
这里的鸭子输入注释更能说明Ruby和Python比C#更动态的事实。它与OO Nature并没有任何关系。
(我认为)Bellware的意思是,在Ruby中,一切都是对象。甚至一堂课。类定义是对象的实例。这样,我们可以在运行时为其添加/更改/删除行为。
另一个很好的例子是NULL也是一个对象。在红宝石中,一切都是一个对象。整体上具有如此深的OO允许使用一些有趣的元编程技术,例如method_missing。
回答
IMO,它实际上是在过度定义"面向对象",但是他们所指的是Ruby与C#,C ++,Java等不同,它没有使用定义类的方法-我们实际上只能直接使用对象。相反,在Cfor中,我们定义了一些类,然后必须通过new关键字将其实例化为对象。关键是我们必须在Cor中声明一个描述它的类。此外,在Ruby中,所有内容(例如,偶数)都是对象。相反,Cstill保留了对象类型和值类型的概念。实际上,我认为这说明了他们对Cand其他类似语言的理解-对象类型和值类型表示类型系统,这意味着我们拥有一个描述类型的整个系统,而不仅仅是使用对象。
从概念上讲,我认为面向对象设计是当今用于处理软件系统复杂性的抽象。该语言是用于实现OO设计的工具-有些使它比其他的更加自然。我仍然认为,从一个更通用,更广泛的定义来看,其他Cand仍然是面向对象的语言。
回答
实际上,这可能归结为这些人看到其他人在cand java中所做的事情,而不是cand java支持OOP。大多数语言都可以在不同的编程范例中使用。例如,我们可以使用cand方案编写过程代码,并且可以使用Java进行功能样式的编程。它更多地是关于我们正在尝试做什么以及语言支持什么。
回答
我只听了引发我们问题的播客的前6至7分钟。如果他们的意图是说Cisn不是纯粹的面向对象的语言,那实际上是正确的。 Cis中的所有内容都不是对象(尽管装箱会创建一个包含相同值的对象,但至少不是图元)。在Ruby中,一切都是对象。达伦(Daren)和本(Ben)在讨论"鸭型"时似乎涵盖了所有基础,因此我不再赘述。
这个差异(所有对象与所有非对象之间的差异)是否是实质性/重要的,这是我无法轻易回答的问题,因为我在Ruby中没有足够的深度将其与C#进行比较。自从30年前这是第一种纯OO语言以来,在座的那些了解Smalltalk的人(我虽然不希望,但我不知道)可能一直很有趣地看着Ruby运动。
回答
那确实是一个抽象播客!
但是我看到他们得到的是什么,他们只是被Ruby Sparkle所吸引。 Ruby允许我们执行C语言和Java程序员甚至不会想到的事情,这些事情的+组合使我们实现了无限的梦想。
向内置String类添加新方法,感觉就像是,传递未命名的代码块以供其他人执行,混入...常规人员不习惯于对象与类模板的变化不大。
肯定是一个全新的世界。
至于Cguys不够面向对象的话...请不要把它放在心上。当我们对单词感到困惑时,只要把它当作我们所说的话即可。 Ruby对大多数人都是这样做的。
如果在最近的十年中我不得不向人们推荐一种语言供人们学习,那就应该是Ruby。我很高兴。尽管有些人可能会要求使用Python。但它就像我的意见..男人! :D
回答
更新:这是新一波潮流。这表明我们到目前为止一直在做的所有事情都已过时。
到现在为止,我们一直在关注静态类,而没有释放面向对象开发的力量。我们一直在做"基于类的开发"。类是用于创建对象的固定/静态模板。创建一个类的所有对象都是相等的。
例如只是为了说明我一直在胡言乱语...让我借用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
与传统的基于类的继承相比,这种想法是一种更强大的继承状态和行为的方式。在某些"特殊"情况下(我尚未了解),它为我们提供了更大的灵活性和控制力。这允许诸如混入(在没有类继承的情况下使用行为)之类的东西。
通过挑战我们如何思考问题的基本原语,"真正的OOP"在某种程度上就像"矩阵"一样……我们可以循环使用WTF。像这样..其中Container的基类可以是Array或者Hash,基于生成的随机数在0.5的哪一侧。
class Container < (rand < 0.5 ? Array : Hash) end
Ruby,javascript和新团队似乎是开创这一点的人。我仍然不喜欢这个...阅读并尝试理解这种新现象。似乎很强大..太强大了..有用吗?我需要我的眼睛再张开一点。有趣的时光..这些。
回答
我不认为这是专门针对鸭子的打字。例如,Csupports已经限制了鸭子的输入,那么我们可以在实现MoveNext和Current的任何类上使用foreach。
鸭子类型的概念与Java和C#等静态类型的语言兼容,基本上是反射的扩展。
静态类型与动态类型实际上就是这种情况。两者都是适当的,因为有这样的事情。在学术界之外,这真的不值得争论。
垃圾代码可以用任何一种编写。优秀的代码都可以用任何一种编写。一个模型完全没有其他模型无法做到的功能。
真正的区别在于所完成编码的性质。静态类型减少了自由度,但是优点是每个人都知道自己在处理什么。即时更改实例的机会非常强大,但是代价是很难知道我们要处理的内容。
例如,对于Java或者Cintellisense而言,IDE很容易,IDE可以快速生成各种可能性的清单。对于Javascript或者Ruby,这变得更加困难。
对于某些事情,例如生成供他人使用的API,静态类型具有真正的优势。对于其他人来说,例如快速生产原型,优势就在于动态。
值得在技能工具箱中对两者进行理解,但远不及了解我们已经在实际中使用过的工具重要。
回答
OO有时被定义为面向消息的。这个想法是方法调用(或者属性访问)实际上是发送给另一个对象的消息。接收对象如何处理消息已完全封装。该消息通常对应于随后执行的方法,但这只是实现细节。例如,我们可以创建一个包罗万象的处理程序,无论消息中的方法名称如何,该处理程序都将执行。
像C中的静态OO没有这种封装。消息必须与现有的方法或者属性相对应,否则编译器会抱怨。但是,诸如Smalltalk,Ruby或者Python之类的动态语言确实支持"基于消息的" OO。
因此,从这个意义上讲,Cand其他静态类型的OO语言不是真正的OO,正弦方式缺乏"真正"的封装。
回答
在面向对象的语言中,对象是通过定义对象而不是类来定义的,尽管类可以为给定抽象的特定cookie定义提供一些有用的模板。在例如C之类的面向类的语言中,对象必须由类定义,并且这些模板通常在运行时被固定和打包,并使其不可变。这种必须在运行时之前定义对象并且对象的定义是不可变的任意约束不是一个面向对象的概念;它是面向阶级的。
回答
面向对象是一个概念。该概念基于某些思想。这些想法的技术名称(实际上是随时间演变而来的原理,但从最初的一个小时开始就没有出现过),在此已不再赘述。我宁愿尽我所能地对此进行简单和非技术性的解释。
OO编程的思想是存在对象。对象是小的独立实体。这些实体可能具有嵌入式信息,也可能没有。如果他们拥有此类信息,则只有实体本身可以访问或者更改它。实体通过在彼此之间发送消息来彼此通信。将此与人类进行比较。人类是独立的实体,内部数据存储在他们的大脑中,并且通过交流(例如,互相交谈)相互交流。如果我们需要其他人的知识,则不能直接访问它,我们必须问他一个问题,他可能会回答我们,告诉我们我们想知道什么。
基本上就是这样。这是面向对象编程背后的真实想法。编写这些实体,定义它们之间的通信,并使它们相互作用以形成一个应用程序。这个概念不限于任何语言。这只是一个概念,如果我们使用C#,Java或者Ruby编写代码,那并不重要。通过一些额外的工作,即使它是一种功能语言,它也可以用纯C语言完成,但它提供了该概念所需的一切。
现在,不同的语言已经采用了这种面向对象编程的概念,当然,这些概念并不总是相等的。例如,某些语言允许其他语言禁止的行为。现在涉及的概念之一是类的概念。有些语言有课程,有些则没有。类是对象外观的蓝图。它定义对象的内部数据存储,定义对象可以理解的消息,以及是否存在继承(对于OO编程不是强制性的!),类还定义了从哪个其他类(或者允许多重继承的类)。此类继承(以及存在选择性继承的属性)。创建了这样的蓝图后,我们现在可以根据此蓝图生成无限数量的对象。
但是,有些OO语言没有类。然后如何构建对象?好吧,通常是动态的。例如。我们可以创建一个新的空白对象,然后向其动态添加内部结构,例如实例变量或者方法(消息)。或者,我们可以复制一个已经存在的对象及其所有属性,然后对其进行修改。或者可能将两个对象合并为一个新对象。与基于类的语言不同,这些语言非常动态,因为我们可以在运行时动态地生成对象,而开发人员甚至在开始编写代码时就没有想到过。
通常,这种动态有代价:语言越动态,语言(对象)的浪费就越多,并且一切变得越慢,因为程序流也非常动态,并且如果没有机会,编译器很难生成有效的代码。预测代码或者数据流。 JIT编译器一旦知道了程序流,就可以在运行时优化其中的某些部分,但是由于这些语言是如此动态,因此程序流可以随时更改,从而迫使JIT放弃所有编译结果并重新编译相同的代码再三,一而再再而三。
但这只是一个很小的实现细节,与基本的OO原理无关。没有人说过对象在运行期间需要是动态的或者必须可更改的。维基百科说得很好:
Programming techniques may include features such as information hiding, data abstraction, encapsulation, modularity, polymorphism, and inheritance.
http://zh.wikipedia.org/wiki/面向对象的编程
他们可能会也可能不会。这不是强制性的。强制性仅仅是对象的存在,并且它们必须具有彼此交互的方式(否则,如果对象之间无法交互,则它们将毫无用处)。
回答
我们问:"有人能给我举一个我可以用红宝石做的奇妙事例的例子吗,而我用坎德不能做的事例举了这种不同的oop方法?"
活动记录就是一个很好的例子,ORM内置在轨道中。模型类是基于数据库模式在运行时动态构建的。