我刚刚了解到,在Java中,覆盖和隐藏之间存在区别(静态方法隐藏不被覆盖),这意味着Java使用早期和晚期绑定。
是否存在类似于隐藏方法的内容,或者只是方法覆盖?
答案 0 :(得分:10)
Java有三种不同的"方法":实例方法,静态方法和构造函数。 Ruby只有一个:实例方法。
在Java中,静态方法必须与实例方法的行为不同,因为类不是对象。它们没有类,因此没有超类,所以没有什么可以覆盖的。在Ruby中,类就像任何其他对象一样是对象,它们有一个类,它可以有一个超类,因此子类可以覆盖超类方法。
注意:您可能已经听说过Ruby中的类方法或单例方法。这是个谎言。好吧,好吧,不是谎言。这是我们使用的便捷速记,因为"类方法"比#34;类对象的单例类"的常规实例方法更容易发音......但这正是它的本质。没有课程方法。
在Ruby中,每个对象都可以拥有自己的方法。这些被称为"单身方法"。类是任何其他对象的对象,因此它们也可以使用单例方法。当单例方法所属的对象是一个类时,我们将该方法称为类方法。但这正是我们所说的,类方法和单例方法之间没有区别。
实际上,在Ruby中,每个对象都有一个单例类。单例类与对象的关系为1:1:对象只有一个单例类,每个单例类只有一个实例,即它的对象。那么,当我在上面说过,对象可以有方法,那些方法被称为单例方法?嗯,这也是一个谎言。 Singleton方法实际上只是标准实例方法,恰好在对象的单例类中定义,因此在该对象上只能被称为 (因为该对象是其单例类的唯一实例) )。
因此,当在单例类中定义方法时,我们将其称为单例方法,当单例类属于类时,我们将其称为类方法,但它只是实例方法。 (顺便说一句:模块的工作方式相同。在这种情况下,它们被称为模块方法,有时也称为模块功能"。)
对象的class
指针始终指向其单例类。然后,对象的实际类是单例类的superclass
,即单例类的superclass
指针指向对象的实际类。 (除非有mixins,它们成为类的超类,它们被混合到一起,所以如果你将一个模块混合到一个单例类中,模块就会成为单例类的超类,而旧的超类成为模块的超类,或者相反,它包括代理类。)
这意味着方法查找,这是OO语言中最常执行的操作,变得非常简单且非常快:抓住对象,抓住它的class
指针,看看方法是否存在,抓取超类指针,查看方法是否存在,抓住超类指针......直到找到方法。
这确实意味着反射变得更复杂,但反射并不是一项对性能至关重要的操作。例如,如果你向一个对象询问它的类,你就不能简单地返回class
指针,因为它总是它的单例类,因此没有很多信息。你必须获得超类和超类的超类等,直到你最终得到一个不是单例类或包含代理类的类。
但是方法查找本身非常简单,super
总能达到预期效果。
特别是,当你创建一个新类时,超类的单例类成为子类的单例类的超类,因此"类方法"像你期望的那样继承。
所以,回顾一下:虽然Java有三种不同的"方法"具有不同的继承行为(实例方法得到继承,静态方法没有,构造函数得到继承,但有super
调用限制),Ruby只有一个。但是,它有三种不同的类:常规类,单例类和包含代理类(在将模块混合到类中时,作为mixin的代理创建)。后两者也被称为"虚拟类"在YARV中,使用最广泛的Ruby实现。
最后一件事:还有所谓的全球方法"有时被称为"全球程序"或者"全球职能"。再一次,正如你可能已经猜到的那样,这些都不存在。当您在任何类之外定义方法时,它隐式地成为Object
的私有实例方法,因此可用于每个对象。
[我忽略了两件事:BasicObject
和prepend
。这些问题有些复杂,特别是后者。但主要的心理模型仍然存在。]