Ruby隐藏与覆盖

Jav*_*ier 5 ruby overriding method-hiding

我刚刚了解到,在Java中,覆盖和隐藏之间存在区别(静态方法被隐藏而不是覆盖),这意味着Java使用早期和晚期绑定.

有没有类似于方法隐藏的东西,或者它只是方法覆盖?

Jör*_*tag 10

Java有三种不同的"方法":实例方法,静态方法和构造函数.Ruby只有一个:实例方法.

在Java中,静态方法的行为必须与实例方法不同,因为类不是对象.它们没有类,因此没有超类,所以没有什么可以覆盖的.在Ruby中,类就像任何其他对象一样是对象,它们有一个类,它可以有一个超类,因此子类可以覆盖超类方法.

注意:您可能已经听说过Ruby中的类方法或单例方法.这是一个谎言.好吧,好吧,不是谎言.这是我们使用的一种方便的简写,因为"类方法"比"类对象的单例类的常规实例方法"更容易发音......但这正是它的本质.没有类方法.

在Ruby中,每个对象都可以拥有自己的方法.这些被称为"单身方法".类是任何其他对象的对象,因此它们也可以使用单例方法.当单例方法所属的对象是一个类时,我们将该方法称为类方法.但这就是我们所说的,类方法和单例方法之间没有区别.

实际上,在Ruby中,每个对象都有一个单例类.单例类与对象的关系为1:1:对象只有一个单例类,每个单例类只有一个实例,即它的对象.那么,当我在上面说过,对象可以有方法,那些方法被称为单例方法?嗯,这也是一个谎言.Singleton方法实际上只是标准实例方法,它恰好在对象的单例类中定义,因此只能在该对象上调用(因为该对象是其单例类的唯一实例).

因此,当在单例类中定义方法时,我们将其称为单例方法,当单例类属于类时,我们将其称为类方法,但它只是实例方法.(BTW:模块以相同的方式工作.在这种情况下,它们被称为模块方法或有时称为"模块功能".)

class对象的指针始终指向其单例类.然后,对象的实际类是superclasssingleton类的superclass实际类,即singleton类的指针指向对象的实际类.(除非有mixins,它们成为类的超类,它们被混合到一起,所以如果你将一个模块混合到一个单例类中,模块就会成为单例类的超类,而旧的超类成为模块的超类,或者相反,它包括代理类.)

这意味着方法查找(这是OO语言中最常执行的操作)变得非常简单且非常快:抓住对象,抓住它的class指针,查看方法是否存在,抓取超类指针,查看是否方法就在那里,抓住超类指针......直到找到方法.

它确实意味着反射变得更复杂,但反射并不是一个对性能至关重要的操作.例如,如果你向对象询问它的​​类,你不能简单地返回class指针,因为它总是它的单例类,因此不是很有用.你必须得到超类,超类的超类等,直到你最终得到一个不是单例类或包含代理类的类.

但是方法查找本身非常简单,并且super始终能够满足您的期望.

特别是,当您创建一个新类时,超类的单例类将成为子类的单例类的超类,因此"类方法"将像您期望的那样继承.

因此,回顾一下:虽然Java有三种不同类型的"方法"具有不同的继承行为(实例方法得到继承,静态方法却没有,构造函数得到继承但有这种super调用限制),Ruby只有一种.但是,它有三种不同的类:常规类,单例类和包含代理类(在将模块混合到类中时,作为mixin的代理创建).后两者在YARV中也被称为"虚拟类",YARV是使用最广泛的Ruby实现.

最后一件事:还有所谓的"全球方法",有时称为"全球程序"或"全球功能".再次,正如您可能已经猜到的那样,这些并不存在.当您在任何类之外定义方法时,它隐式地成为Object每个对象的私有实例方法,因此可用于每个对象.

[我在这里忽略了两件事:BasicObjectprepend.这些问题有些复杂,特别是后者.但主要的心理模型仍然存在.]