Rob*_*t K 80 ruby language-features eigenclass
我错过了某个地方的备忘录,我希望你能解释一下这个.
为什么对象的本征类不同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 << self将设置self以Foo.class用于类方法的定义/属性.
我只是困惑吗?或者,这是Ruby元编程的偷偷摸摸的伎俩吗?
Dav*_*ler 121
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.这个子类被称为Foo的eigenclass.因此,def a创建一个名为ain Fooeigenclass 的新方法,可以通过常规方法调用语法访问: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.
希望这可以帮助.
小智 46
最简单的答案:本征类无法实例化.
class F
 def eigen
  class << self 
   self
  end
 end
end
F.new.eigen.new #=> TypeError: can't create instance of virtual class
| 归档时间: | 
 | 
| 查看次数: | 14290 次 | 
| 最近记录: |