[英]Ruby eigenclass unexpected behaviour
首先,让我们添加一个方法来检索“从此博客帖子中复制”的特征类
class Object
def eigenclass
class << self
self
end
end
end
然后创建一个简单的类
class A
end
puts A.new.eigenclass.superclass # => A
puts Class.new.eigenclass.superclass # => #<Class:Object>
我期待第二次投入输出Class
任何线索为什么会这样?
通过puts A.new.eigenclass.superclass
,您#eigenclass
在类A的实例上调用#eigenclass
。我将从后台开始解释eigenclass实际上是如何工作的,然后将继续告诉代码中发生了什么。
背景故事:
EigenClass是一个隐藏类,它包含仅适用于该特定对象的单例方法。
所以对于obj = Foo.new
,类层次结构实际上看起来像:
obj --eigenclass - >#> - (超类) - > A.
代替:
obj - (类) - > A.
使用#eigenclass
劫持自我后,可以生成隐藏的类。
现在,在Ruby中, Class是一个对象。 这也意味着#eigenclass
应该显示A
的隐藏本征类(其中保留了A的sigleton方法)。
A - (本征类) - ># - (超类) - >#
现在它之所以显示#而不是A
是因为Ruby以非常漂亮的模式组织了类,超类和特征类。 这可以用示例显示,而不是用令人困惑的词语引用它:
A.superclass #=> Object
A.eigenclass #=> #<Class: A>
A.eigenclass.superclass #=> #<Class: Object> => Eigenclass of Object
A.eigenclass.superclass == Object.eigenclass #=> true
类的本征 类的超类是原始类的超类的本征类 。
现在, Class.new.eigenclass.superclass
你的情况: Class.new.eigenclass.superclass
,现在这是不言自明的。 Class.new
对应一个新的匿名类,比如B
,你实际上是在调用eigenclass.superclass
。 由于B
的超类是Object,B的本征类的超类是B
的超类的本征类。
我尽力用例子来解释。 请在下面的评论中进一步澄清; 将相应更新答案。 补充(来自Pragmatic MR): 。
在上图中, D
继承自C
所以D.eigenclass.superclass
是(D的超类)[它是C]的eigneclass。 现在C的超类是Object ..所以是相同的逻辑。
问候
从该博文中,您可以构建一个类似的图表:
+------------------+ +-------------------+
| Object |- eigenclass ->| Object eigenclass |
+------------------+ +-------------------+
^ ^
| superclass superclass |
+------------------+ +-------------------+
| A |- eigenclass ->| A eigenclass |
+------------------+ +-------------------+
^
| superclass
+-------+ +------------------+
| A.new |- eigenclass ->| A.new.eigenclass |
+-------+ +------------------+
试图找到A实例的本征类的超类表明它指向A
类。
A.new.eigenclass.superclass # => A
Class.new
返回Class对象的实例,即一个新类。 这是一个类,就像A
类一样。
Class.new.class # => Class
A.class # => Class
A的超类和Class.new的超类都是隐式的Object
。
Class.new.superclass # => Object
A.superclass # => Object
因为A的超类是Object
,A的本征类的超类是Object的特征类。
Object.eigenclass # => #<Class:Object>
A.eigenclass.superclass # => #<Class:Object>
A.eigenclass.superclass == Object.eigenclass # => true
同样的,找到的eigenclass的超Class.new
产生对象的eigenclass
Class.new.eigenclass.superclass # => #<Class:Object>
之间的区别Class.new
和A.new
是Class.new
本身就是一类,因此可以构建新的对象,而A.new
不能。
Class.new.new # => #<#<Class:0x007f86b50d8f70>:0x007f86b50d8f20>
A.new.new # => NoMethodError: undefined method `new' for #<A:0x007f86b50cbf50>
类的本征类具有整个类的本体类的阴影层次,用于类的祖先,它们都在本征类和类之间。 这是因为期望类继承其祖先的类方法。 例如,如果你确定def Numeric.kind_of_number?() true end
,你会期望Fixnum.kind_of_number?
是真实的。 所以你需要将Numeric的本征类作为Fixnum的本征类的祖先。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.