动态语言如Smalltalk、Ruby和Python的对象模型主要区别是什么

3 投票
2 回答
2111 浏览
提问于 2025-04-15 17:58

最近我开始深入了解Ruby的对象模型,虽然之前我只是使用过Ruby和Python的功能,但我对这些语言之间的不同之处产生了好奇。

几年前,我接触过Smalltalk的Squeak。Smalltalk常被认为是一个经典的面向对象语言,这也是我对它感兴趣的原因。Ruby的对象模型没有区分对象和类,存在的单例对象让每个对象在需要时都可以作为原型进行扩展。我了解到这些都是通过元对象协议来定义的。这些特性让编程变得比一些不那么动态的语言,比如C++或Java,简单得多。

你能给我讲讲动态语言,特别是Smalltalk、Python和Ruby在实现元对象协议方面有什么不同吗?

2 个回答

2

我记得Python和Smalltalk之间最大的区别在于属性的隐私处理。在Smalltalk中,我需要定义属性并且必须立刻生成所有的访问方法(幸运的是,Dolphin Smalltalk做到了这一点),然后才能使用它们。另一方面,在Python中,所有的东西都是可以访问的,甚至是那些被认为是私有的属性(这些属性前面有两个下划线,经过处理后变成三个下划线)。有人可能会说,这样做有潜在的危险——比如将来你需要对某个属性进行一些操作时,可能会出问题。不过,Python用一种优雅的方式解决了这个问题,那就是使用属性

我喜欢这种可以随意访问任何东西的想法。只要我知道自己在做什么,我就可以这样做 :-)

2

在Python中,每个对象都有一个命名空间,也就是对象的“属性”。这些属性可以是方法、简单的其他对象的引用(可以调用的或不可调用的),或者是通过描述符动态生成的(普通属性可以在实例中或类中存在,但描述符——包括作为描述符的函数——只能在类中使用,而不能在实例中使用;所以特别方法只有在类中定义时才算特别,而不是在实例中)。处理属性的内置函数和特殊方法(比如getattrsetattr__getattr____setattr__等)在对象的命名空间中工作方式是一样的,无论是指普通属性还是其他。

关键点是,对于任何对象a,在Python中,a.b可能是一个方法(或者其他可调用的东西),也可能不是:Python编译器并不知道(也不在乎),你可以把a.b当作引用使用,比如作为参数传递、作为结果返回、添加到列表中等等,这些操作都不意味着要调用 a.b。如果你想要(尝试)调用a.b,你需要明确地加上括号:a.b(),如果你想不带参数地调用它。

在Ruby中,对象的方法和属性是分开存放的命名空间(所以你可以有一个方法和一个属性同名的对象,而在Python中这是不允许的),而且“只提到”一个没有参数的方法会隐式地调用它(所以c=a.b可能只是获取一个属性引用,也可能是在调用a.b();如果b同时指代了的一个方法和一个属性,我不记得用什么规则来区分了)。因此,如果你想单纯地获取方法引用(比如存放在某个容器中或作为参数或返回值使用),然后再进行调用,你需要使用不同的语法。

Smalltalk也像Ruby一样有分开的命名空间,但在这种情况下,你无法引用某个对象的“非方法”属性(每个对象只能“看到”自己的属性),所以这种模糊性不会出现(但你仍然需要使用特定的消息来提取并随后调用“方法引用”)。

撰写回答