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
Run Code Online (Sandbox Code Playgroud)
我的逻辑系列等同于特征类,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
Run Code Online (Sandbox Code Playgroud)
这有效,并且相当于def Foo.a
,但它的工作方式有点微妙.秘诀在于self
,在该上下文中,指的是对象Foo
,其类是一个唯一的匿名子类Class
.这个子类被称为Foo
的eigenclass.因此,def a
创建一个名为a
in Foo
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
Run Code Online (Sandbox Code Playgroud)
这个例子和最后一个例子相同,但最初可能很难说. 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.
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
小智 46
最简单的答案:本征类无法实例化.
class F
def eigen
class << self
self
end
end
end
F.new.eigen.new #=> TypeError: can't create instance of virtual class
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14290 次 |
最近记录: |