我试图理解 Ruby 的“class << self”背后的底层机制。 我了解如何使用它并且我知道这是一个单例类定义,但我想真正了解它是如何工作的。
这是一个例子:
class Klass
puts "#{self}" #=> Klass
class << self
puts "#{self}" #=> #<Class:Klass>
end
end
puts Klass.class #=> Class
puts Klass.singleton_class #=> #<Class:Klass>
为什么这些语句会输出它们输出的内容? Class
和Class:Klass
、class和singleton_class有什么区别??
最佳答案
irb>
irb>
irb> class FightClub; def rule_1; 'You do not talk about FIGHT CLUB.'; end; end
=> nil
irb> club1=FightClub.new
=> #<FightClub:0x007fb4240c48d0>
irb> club2=FightClub.new
=> #<FightClub:0x007fb42394b770>
irb>
irb>
irb> def club2.rule_2; rule_1; end
=> nil
irb> club1.rule_1
=> "You do not talk about FIGHT CLUB."
irb> club1.rule_2
NoMethodError: undefined method `rule_2' for #<FightClub:0x007fb4240c48d0>
from (pry):6:in `__pry__'
irb>
irb> club2.rule_1
=> "You do not talk about FIGHT CLUB."
irb> club2.rule_2
=> "You do not talk about FIGHT CLUB."
irb>
到目前为止很简单..
irb>
irb> club1.class.__id__ # FightClub
=> 70205838357120
irb> club2.class.__id__ # FightClub
=> 70205838357120
irb>
irb>
irb> club2.singleton_class # eigenclass of this instance
=> #<Class:#<FightClub:0x007fb42394b770>>
irb> club1.singleton_class
=> #<Class:#<FightClub:0x007fb4240c48d0>>
irb> club1.class.__id__ == club2.class.__id__
=> true
irb> club1.singleton_class.__id__ == club2.singleton_class.__id__
=> false
irb> club1.singleton_class.superclass.__id__ ==
irb* club2.singleton_class.superclass.__id__ # 70205838357120
=> true
irb>
irb>
irb> club1.singleton_class.instance_methods.select{|m| m.to_s.start_with?('rule')}
=> [:rule_1]
irb> club2.singleton_class.instance_methods.select{|m| m.to_s.start_with?('rule')}
=> [:rule_2, :rule_1]
irb>
irb> club1.singleton_methods
=> []
irb> club2.singleton_methods
=> [:rule_2]
irb>
如果还不清楚:
singleton_class
是 eigenclass的一个实例。这里有个好explanation of eigenclass .- 任何实例方法(本例中的
rule_2
)都是singleton_methods
并在 eighenclass 上创建。 superclass
所有特征类都是相同的(并且是 = instance.class)。- 意见:所以实际上
Class
代表any_ruby_object
类的实例实际上是any_ruby_object。 singleton_class
而不是any_ruby_object.class
不相关但只是为了让它变得困惑:
irb> club2.methods.select{ |m| m.to_s.start_with?('rule') }
=> [:rule_2, :rule_1]
irb> club1.methods.select{ |m| m.to_s.start_with?('rule') }
=> [:rule_1]
irb>
关于ruby - 在 Ruby 中使用类 << self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26190117/