为什么 self 与类内部的 MyClass 不一样
因为class关键字总是改变作用域:
class MyClass
puts self #=> MyClass
class <<self
puts self #=>MyClass’s singleton class
end
end
更具体地说,为什么方法委托对 self 不可用
在类 内
class MyClass
def self.delegate
puts "executing MyClass.delegate()"
end
class <<self
delegate
end
end
--output:--
1.rb:8:in `singleton class': undefined local variable or method `delegate' for #<Class:MyClass> (NameError)
from 1.rb:7:in `<class:MyClass>'
from 1.rb:1:in `<main>'
请注意,以下构造是等效的:
class MyClass
def self.delegate
puts "executing MyClass.delegate()"
end
end
MyClass.delegate
--output:--
executing MyClass.delegate()
和:
class MyClass
class <<self
def delegate
puts "executing MyClass.delegate()"
end
end
end
MyClass.delegate
--output:--
executing MyClass.delegate()
因此,您的代码相当于:
class MyClass
class <<self
def delegate
puts "executing MyClass.delegate()"
end
delegate
end
end
如果你暂时忽略外部的 MyClass,那么你定义了一个这样的类:
class <<self
def delegate
puts "executing MyClass.delegate()"
end
delegate
end
同样的结构可以这样复制:
class Dog
def bark
puts “woof”
end
bark
end
这将产生相同类型的错误:
1.rb:7:in `<class:Dog>': undefined local variable or method `bark' for Dog:Class (NameError)
from 1.rb:1:in `<main>'
当你调用一个方法并且你没有指定一个接收者时,ruby 使用当前分配给 self 变量的任何对象作为接收者。
在方法内部,ruby 将调用该方法的对象分配给 self 变量。调用方法的对象和定义方法的类(对象)不是一回事。
在类内部,但在任何方法定义之外,ruby 将类(对象)分配给 self。
请注意,可以在 Dog 类中调用 def 的是 Dog 类的 实例,例如吠()。类似地,单例类的实例可以在单例类中调用def,例如delegate()——单例类本身不能在单例类中调用def。它们被称为单例类的全部原因是因为单例类只有一个实例——在您的情况下,单例类的一个实例是 MyClass。结果MyClass可以调用delegate(),但是单例类不能调用delegate()。
我真的不明白 eignclass 上的类方法是什么
但是。
就我个人而言,我不使用术语eigenclass。在我看来,ruby 已经决定这个词是singleton class。如果您查看 Object 类的文档,其中没有包含 eigenclass 的方法名称,但其中有包含 singleton class 的方法名称。
所有对象都有一个单例类。单例类是一个对象。因此,每个单例类也有一个单例类——这意味着单例类的链是无限的:
class Dog
end
s1 = Dog.singleton_class
puts s1
s2 = s1.singleton_class
puts s2
s3 = s2.singleton_class
puts s3
--output:--
#<Class:Dog>
#<Class:#<Class:Dog>>
#<Class:#<Class:#<Class:Dog>>>
这意味着你可以做这样的事情:
class Dog
class <<self #s1
class <<self #s2
def greet #Instances of s2 can call greet, and the only instance of s2 is s1.
puts "hello"
end
end
end
end
class Dog
class <<self
#Inside here self = Dog's singleton class = s1
greet #equivalent to Dogs_singleton_class.greet
end
end
--output:--
hello
但是,我以前从未见过有人在他们的代码中使用过单例类 (s2) 的单例类。很久很久以前,我曾经回答过一个问题,但没人知道我在说什么。
有一些方法查找图here,可能很有用。