为什么许多鸭子式动态编程语言会使用基于类的方法而不是基于原型的OOP?


23

由于许多动态编程语言都具有鸭类输入法的功能,并且它们还可以随时打开和修改类或实例方法(例如RubyPython),因此……

问题1)动态语言课程的需求是什么?为什么要用这种方式设计语言,以将类用作某种“模板”,而不是以原型方式使用而只是使用对象?

另外的JavaScript是原型为基础,但CoffeeScript的(JavaScript的加强版),选择基于类的方式。它也适用于相同的Lua(原型为基础)和MoonScript(类为主)。此外,ES 6中还有一门课。所以……

问题2)是否暗示着,如果您尝试改进基于原型的语言,则应将其更改为基于类的语言?如果没有,为什么要这样设计?


9
许多程序员不想学习新知识。(太陌生和“困难”)。因此,所有这些基于类的库和可编译为它们的语言。
Thomas Eding

1
我同意Thomas的观点,但有趣的是,在您学习了动态方法之后,它实际上更容易(不难)。对象的概念仍然存在,只是可以更改对象而无需先重新编译一些愚蠢的“蓝图”。如果我想在椅子上放一条第五条腿,我不想先改变一个蓝图,我只想添加一条腿。我认为动态语言更紧密地模拟了现实。
Lonnie Best

1
OOP是在必须声明类型的静态类型的上下文中发明的。在这里,类是从记录和模块向前迈出的明智一步。基于原型的OOP一直只是Self语言的一个有趣的研究主题,并且以某种方式使其成为JavaScript成为最简单的方法,以将“ OOP”流行语打造成一种基本的功能语言。令人高兴的是,您可以在原型之上实现类。尽管我喜欢元对象,但将类与其实例分离开来使编写结构良好,简单,松散耦合的代码变得更加容易。
阿蒙2015年

3
首先,第一件事:JavaScript本身支持class下一个ECMAScript标准(ECMAScript 6)的关键字。对JavaScript中的类的支持已经计划了很长时间。现在说的是-类只是语法糖,对于相同类型的对象而言,模型更容易推理。在JS中就是这种方式,而在Python和其他动态语言中就是这种方式。
本杰明·格伦鲍姆

1
@BenjaminGruenbaum“ ...类只是语法糖...”哇,对我来说这是一个相当新颖的主意,对于像ruby和python这样的语言,似乎使用对象还是使用对象都没有关系。类作为模板-两者都可以随时进行修改。而且,它们如何处理继承也都没有关系。因此,对于动态语言,也许无需区分基于类的方法和基于原型的方法:)
iceX 2015年

Answers:


12

问题1)使用动态语言的班级需要什么?为什么将语言设计为使用类作为某种“模板”,而不是使用原型方法并仅使用对象?

Simula是第一种面向对象的语言(即使它没有被称为“ OO”)也没有继承。继承是在Simula-67中添加的,它是基于类的。

大约在同一时间,艾伦·凯(Alan Kay)开始研究他的新编程范例的概念,后来他将其命名为“面向对象”。他真的很喜欢继承并且想用他的语言来继承,但是他也真的不喜欢课堂。但是,他想不出没有类就可以继承的方法,因此他决定不喜欢类而不是喜欢继承,因此他设计了Smalltalk的第一个版本,Smalltalk-72,没有类,因此也没有继承。

几个月后,Dan Ingalls提出了一个类的设计,其中类本身是对象,即元类的实例。艾伦·凯(Alan Kay)发现此设计的适用性略低于旧设计,因此Smalltalk-74的设计带有类,并且基于类进行继承。

在Smalltalk-74之后,艾伦·凯(Alan Kay)感到Smalltalk朝着错误的方向发展,实际上并不能代表OO的全部内容,因此他提议团队放弃Smalltalk并重新开始,但他被选出。因此,紧随其后的是Smalltalk-76,Smalltalk-80(向研究人员发布的第一个版本的Smalltalk),最后是Smalltalk-80 V2.0(第一个商业发布的版本,并且该版本成为ANSI Smalltalk的基础) 。

由于Simula-67和Smalltalk-80被视为所有OO语言的祖父母,因此几乎所有随后的语言都盲目地复制了类的设计和基于类的继承。几年后,当诸如基于混合而不是类的继承,基于对象而不是基于类的继承的委托之类的其他想法浮出水面时,基于类的继承已经变得根深蒂固。

有趣的是,Alan Kay当前的语言是基于原型委托。


“……艾伦·凯的当前语言……”是……?
哈维尔2015年

@Javier:我不认为它有名称,并且系统名称一直在变化。
约尔格W¯¯米塔格

这应该是一个很好的答案,以指向下一次有人将继承列为OO的要求时:)
Hey

1
@iceX:艾伦·凯(Alan Kay)创立了Viewpoints研究院,致力于他的想法。不幸的是,信息确实散布在网站上。
约尔格W¯¯米塔格

3
艾伦·凯(Alan Kay)在OO上引用:“对我来说,OOP意味着消息传递,本地保留和保护以及状态过程的隐藏以及所有事物的极端后期绑定。这可以在Smalltalk和LISP中完成。在其中可能还有其他系统这是可能的,但我不知道它们。”
Joeri Sebrechts

23

许多程序员更喜欢使用类。这是一个非常容易理解的概念,它是人类关于世界的思维过程的良好模型(也就是说,我们本能地将真实对象与我们认为它们属于的抽象项目组相关联,这就是一个类) 。而且,类使对象类型的推理更容易:在基于类的语言中,应用Liskov替换之类的原理比在其中仅存在可能具有不同方法的对象或者其类型甚至在运行时可能改变的语言中更容易应用,就像JavaScript中一样。

请注意,即使在JavaScript中,大量代码也只是使用原型工具来模拟类。这主要是因为许多程序员更喜欢这样思考。

首选基于类的语言还有另一个原因:将它们编译为有效的代码更加容易。最有效的JavaScript VM可以有效地动态创建类,以随着方法和原型的更改来表示JavaScript对象的类型。有关执行此操作的基本原理,请参见V8的实现说明


4
你的最后一段实际上支持你说的话完全相反:V8证明你并不需要为了编译成高效的基于类的代码在语文课。
约尔格W¯¯米塔格

4
是的,您不需要它们-但是V8(可能还包括Self,尽管我对系统的设计了解不多)有效地创建了虚拟类这一事实意味着从本地使用类的语言开始几乎是肯定更容易,因此最终可能会使JIT花费更少的时间来编译代码。
2015年

11
当然,V8有效地创建GOTOs和寄存器的事实意味着,几乎可以肯定,仅放弃所有抽象并直接在汇编中编写就容易了,因此,最终JIT可能需要花费更少的时间来编译代码。支持更高级别的抽象是编译器的工作。
约尔格W¯¯米塔格

1
是的,但是这是一个折衷,因为更高级别的抽象在大多数情况下更难实现,并且通常会损害运行时性能,尤其是在使用JIT而不是AOT编译器时。我怀疑许多语言设计师出于这些原因中的一个或两个都选择了基于类的结构。我知道这就是为什么我为我正在使用的(否则为动态的)语言选择具有固定成员的类,但只能推测其他语言的原因。
2015年

1
我认为,程序员偏爱“类思维”的唯一方法是,因为这就是我们大多数人的学习方式。我绝对可以记得很多大学同学,尽管几年来他们在理解和理解一些真正的基本面向对象概念时遇到了麻烦。事后看来,这似乎很明显而且很容易。
KChaloux

3

我听说过,在大型项目中,团队的成员在同一个代码上一起工作,灵活的语言(您可以在运行时修改对象的属性和方法)是其他团队成员所不希望的自由具有。

他们想知道,当他们处理一个对象时,该对象将像蓝图所示那样工作,而不是其他雄心勃勃的开发人员决定将其更改为完成自己的任务的某种变形方式。

因此,我能想到的唯一原因是,某人不希望这些出色的动态语言提供灵活性,而是他们希望简化团队开发,调试和自动文档编制。

就个人而言,我已经用两种方法开发了应用程序,并且使用动态语言可以更快地完成工作。我不使用任何旨在将动态语言重新转换为基于类的语言的框架。这样的事情是我品味的回归。


1

对我而言,面向对象操作仅意味着消息传递,本地保留和保护以及状态流程的隐藏以及万物的极端后期绑定-艾伦·凯(Alan Kay)

因此,他在这里所说的是OO就是制作响应消息的黑匣子。从某种意义上说,REST是最终的OO系统,它使用动词(即消息)和资源(即包含一些数据的不透明框)。

因此,为什么有些基于类而另一些基于原型的问题却错了一点,那就是,它们并不重要,因为它们都只是实现。仅使用消息传递而不是方法调用的系​​统与您提到的两个实例一样是OO。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.