【问题标题】:Using class << self in Ruby在 Ruby 中使用 class << self
【发布时间】:2014-10-04 05:52:56
【问题描述】:

我试图了解 Ruby 的“class

这是一个例子:

class Klass
  puts "#{self}" #=> Klass
  class << self
    puts "#{self}" #=> #<Class:Klass>
  end
end

puts Klass.class #=> Class
puts Klass.singleton_class #=> #<Class:Klass>

为什么这些语句会输出它们所输出的内容? ClassClass:Klass,class和singleton_class有什么区别??

【问题讨论】:

标签: ruby metaprogramming


【解决方案1】:
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)。
  • 意见:所以实际上代表any_ruby_object 类的Class 实例实际上是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>

【讨论】:

  • 如果你去掉了所有的 IRB 噪音,代码会更好读。
【解决方案2】:

单例类是一个特殊的类,只存在于该类的实例中,因为即使类定义也是对象,它们的另一个术语是特征类。一种用途是定义仅对定义它们的类实例可用的“类级别方法”或“类级别实例变量”(与类变量不同)。考虑 eigenclass 的另一种方式是它是类的实例,因为正如我们所知,ruby 中的一切都是对象。

这是 Andrea Singh 的一篇文章,我已经阅读了很多次以尝试理解。它在通过 eigenclass 可视化类方法调度方面做得很好:

http://madebydna.com/all/code/2011/06/24/eigenclasses-demystified.html

说实话,解释堆栈溢出有点太元了,我认为您通过尝试示例来尝试理解是正确的。只要记住它是elephants 对象一直向下,直到你到达海龟 BasicObject!

【讨论】:

    【解决方案3】:

    #&lt;Class:Klass&gt;Class 是同一类Class 的不同实例。

    【讨论】:

    • @Stefan 单例类是一个类。 Klass.singleton_class.class # =&gt; Class.
    • 谢谢@sawa,但它们之间有区别吗?
    • @Sergey 正如我所写,它们是不同的实例。就像1 不是2,它们也是。
    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    相关资源
    最近更新 更多