pez*_*ser 11 ruby class-method class-variables class-instance-variables instance-methods
class << self
attr_accessor :n, :totalX, :totalY
end
Run Code Online (Sandbox Code Playgroud)
上面的语法用于定义类实例变量.但是当我考虑语法含义时,它对我没有任何意义,所以我想知道这种类型的语法是否用于任何其他类型的定义.我在这里的困惑是:
class << self
Run Code Online (Sandbox Code Playgroud)
追加运算符通常意味着"向左侧的对象添加右侧的内容".但是在这个块的上下文中,如何将"将此块的内容放入类实例的定义而不是实例"?
出于同样的原因,我很困惑为什么在一个上下文类中,<< self可以定义类实例变量,而在另一个上下文它似乎创建了类变量,例如:
class Point
# Instance methods go here
class << self
# Class methods go here
end
end
Run Code Online (Sandbox Code Playgroud)
lev*_*lex 19
在Ruby中,您可以重新打开现有类并添加方法.也就是说,你可以说:
class Foo
def bob
return "hello from bob"
end
end
Run Code Online (Sandbox Code Playgroud)
这些方法存储在Foo-class 的内部字典(可能是实例变量)中(它只是Class-class的一个实例,因此具有实例变量)
但令人惊讶的是,您还可以向现有对象的实例添加方法
foo = Foo.new
foo2 = Foo.new
def foo.fred
return "I am fred"
end
foo.fred #=> "I am fred"
foo2.fred #=> NoMethodError
Run Code Online (Sandbox Code Playgroud)
但这种方法实际存储在哪里?
事实证明Ruby在幕后创建了一个新类(有时称为单例类,元类或本征类),它被插入到-class与其实例之间的继承层次中Foo.
所以继承关系看起来像这样:
foo < (eigenclass of foo) < Foo < Class
Run Code Online (Sandbox Code Playgroud)
(如果你说foo.superclass你将看不到单例类)
该class << X-syntax是一种方式来获得这种特殊的班级,这样就可以直接操作它.以下代码块完全等效:
def foo.bar
return "xy"
end
# is exactly the same as
class << foo
def bar
return "xy"
end
end
Run Code Online (Sandbox Code Playgroud)
所以之间的相似class Foo < Bar和class << Foo不是偶然的,有传承在这两个事情.
想象class << X为"打开X的元类"
在Ruby中要记住的事情是类本身只是对象.(班级实例Class)如果你说:
class Foo
class << self
def k
return "x"
end
end
end
Run Code Online (Sandbox Code Playgroud)
(在此代码块中self绑定Foo)因此k是本征类的实例方法Foo,这使得它成为一个类方法Foo
所有这些都在关于Pickaxe的类的章节中更清楚地解释了(不幸的是,Web版本不包含图表)和_whys 明显看到Metaclasses