为什么特征类不等于self.class,看起来如此相似呢?

我已经错过了备忘录,我希望你能向我解释这个。

为什么对象的特征类与self.class不同?

 class Foo def initialize(symbol) eigenclass = class << self self end eigenclass.class_eval do attr_accessor symbol end end end 

我的一系列逻辑把特征阶级和class.self我们相当简单:

class << self是一种声明类方法的方法,而不是实例方法。 这是def Foo.bar的快捷方式。

所以在对类对象的引用中,返回self应该和self.class 。 这是因为class << selfclass << self设置为Foo.class来定义类方法/属性。

我只是困惑? 或者,这是Ruby元编程的诡计吗?

class << self不仅仅是一种声明类方法的方法(尽pipe它可以这样使用)。 可能你已经看到了一些用法,如:

 class Foo class << self def a print "I could also have been defined as def Foo.a." end end end 

这个工作,相当于def Foo.a ,但它的工作方式有点微妙。 秘密在于,在这种情况下, self是指对象Foo ,它的类是Class一个独特的匿名子Class 。 这个小类被称为Foo特征类 。 所以def a创build了一个新的方法,称为在Foo的本征类中,可以通过常规的方法调用语法: Foo.a

现在让我们来看一个不同的例子:

 str = "abc" other_str = "def" class << str def frob return self + "d" end end print str.frob # => "abcd" print other_str.frob # => raises an exception, 'frob' is not defined on other_str 

这个例子和最后一个例子是一样的,尽pipe起初可能很难说。 frob的定义不是在String类上,而是在str本征类上定义的,它是String的唯一匿名子类。 所以str有一个frob方法,但String实例一般不会。 我们也可以重写String的方法(在某些棘手的testing场景中非常有用)。

现在我们准备好了解您的原始示例。 在Foo的初始化方法中, self不是指Foo类,而是指Foo某个特定实例 。 它的特征类是Foo一个子类,但它不是Foo ; 它不可能,否则我们在第二个例子中看到的技巧就无法工作。 所以继续你的例子:

 f1 = Foo.new(:weasels) f2 = Foo.new(:monkeys) f1.weasels = 4 # Fine f2.monkeys = 5 # Also ok print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method. 

希望这可以帮助。

最简单的答案:特征类不能被实例化。

 class F def eigen class << self self end end end F.new.eigen.new #=> TypeError: can't create instance of virtual class 

耶胡达·卡茨在解释“ ruby中的元编程:一切都是为了自我 ”

Interesting Posts