Ruby隐藏与重写
我刚刚了解到,在Java中,重写和隐藏(静态方法是隐藏的,而不是重写的)是有区别的,这意味着Java同时使用早期绑定和晚期绑定Ruby隐藏与重写,ruby,overriding,method-hiding,Ruby,Overriding,Method Hiding,我刚刚了解到,在Java中,重写和隐藏(静态方法是隐藏的,而不是重写的)是有区别的,这意味着Java同时使用早期绑定和晚期绑定 是否有类似于方法隐藏的东西,或者它只是有方法覆盖?Java有三种不同的“方法”:实例方法、静态方法和构造函数。Ruby只有一个:实例方法 在Java中,静态方法的行为必须不同于实例方法,因为类不是对象。它们没有类,因此没有超类,因此没有可重写的内容。在Ruby中,类和其他对象一样都是对象,它们有一个类,可以有一个超类,因此子类可以覆盖超类方法 注意:您可能听说过Ruby
是否有类似于方法隐藏的东西,或者它只是有方法覆盖?Java有三种不同的“方法”:实例方法、静态方法和构造函数。Ruby只有一个:实例方法 在Java中,静态方法的行为必须不同于实例方法,因为类不是对象。它们没有类,因此没有超类,因此没有可重写的内容。在Ruby中,类和其他对象一样都是对象,它们有一个类,可以有一个超类,因此子类可以覆盖超类方法 注意:您可能听说过Ruby中的类方法或单例方法。那是谎言。好吧,这不是谎言。这是我们使用的一个方便的速记,因为“类方法”比“类对象的单例类的常规实例方法”更容易发音……但事实正是如此。没有类方法 在Ruby中,每个对象都可以有自己的方法。这些被称为“单例方法”。类是与任何其他对象一样的对象,因此它们也可以有单例方法。当单例方法所属的对象是类时,我们称该方法为类方法。但这正是我们所说的,类方法和单例方法之间没有区别 实际上,在Ruby中,每个对象都有一个单例类。singleton类与对象的关系为1:1:对象只有一个singleton类,每个singleton类只有一个实例,即它的对象。那么,当我在上面提到对象可以有方法时,这些方法称为单例方法?那也是个谎言。单例方法实际上只是标准实例方法,它恰好是在对象的单例类中定义的,因此只能在该对象上调用(因为该对象是其单例类的唯一实例) 因此,当一个方法在一个单例类中定义时,我们称之为单例方法,当单例类属于一个类时,我们称之为类方法,但都只是实例方法。(顺便说一句:模块的工作方式是相同的。在这种情况下,它们被称为模块方法或有时称为“模块函数”。) 对象的
class
指针始终指向其单例类。然后,对象的实际类是单例类的超类
,即单例类的超类
指针指向对象的实际类。(除非存在mixin,mixin将成为它们所混合到的类的超类,因此如果将模块混合到单例类中,则模块将成为单例类的超类,而旧的超类将成为模块的超类,或者更确切地说是其包含代理类。)
这意味着方法查找,这是OO语言中最常执行的操作,变得非常简单和快速:抓取对象,抓取其类
指针,查看方法是否存在,抓取超类指针,查看方法是否存在,抓取超类指针……直到找到方法
这确实意味着反射变得更加复杂,但反射并不是一个性能关键的操作。例如,如果您向一个对象请求它的类,您不能简单地返回类
指针,因为它始终是它的单例类,因此信息量不大。你必须得到超类,以及超类的超类等等,直到你最终得到一个不是单例类或include代理类的类
但是方法查找本身非常简单,super
总是按照您的期望执行
特别是,当您创建一个新类时,超类的singleton类将成为子类的singleton类的超类,因此“类方法”就像您所期望的那样被继承
因此,概括一下:虽然Java有三种不同类型的“方法”,它们具有不同的继承行为(实例方法被继承,静态方法不被继承,构造函数被继承,但有这个super
调用限制),但Ruby只有一种。但是,它有三种不同类型的类:常规类、单例类和包含代理类(在将模块混合到类中时创建为mixin的代理)。后两个在YARV内部也称为“虚拟类”,YARV是使用最广泛的Ruby实现
最后一件事:还有所谓的“全局方法”,有时称为“全局过程”或“全局函数”。同样,正如你可能已经猜到的,这些是不存在的。当您在任何类之外定义方法时,它隐式地成为Object
的私有实例方法,因此可用于每个对象
[我在这里忽略了两件事:BasicObject
和prepend
。这些事情有点复杂,尤其是后者。但主要的心理模型仍然存在。]