为什么特征类不等于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很简单:

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

因此,在对类对象的引用中,返回self应该与self.class相同。 这是因为class << self会设置self ,以Foo.class的类方法定义/属性。

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


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

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创建了一个名为新方法aFoo的eigenclass,通过正常的方法调用的语法访问: 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

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

现在我们准备好了解您的原始示例。 里面Foo的initialize方法, 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

耶胡达卡茨在解释“红宝石中的元编程:一切关于自我”中的精妙之处做得相当不错。

链接地址: http://www.djcxy.com/p/17093.html

上一篇: Why isn't the eigenclass equivalent to self.class, when it looks so similar?

下一篇: Can Ruby print out time difference (duration) readily?