ruby - 在 Ruby 中使用类 << self

标签 ruby metaprogramming

我试图理解 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>

为什么这些语句会输出它们输出的内容? ClassClass: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_classeigenclass的一个实例。这里有个好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/

相关文章:

使用 switch case 设置和获取成员变量的 C++ 元编程

ruby - 带有验证码的表单上的 cucumber 功能

mysql - ActiveRecord 按特定关系的值排序

ruby - Bash - 如何从后台 ruby​​ 脚本获取 STDOUT

ruby - 是否可以在 Ruby 中卡住(使其不可变)类或方法?

rust - 如何在编译时创建字母表数组?

c++ - 检查是否存在嵌套类型别名并有条件地设置类型别名

reflection - 反射到底是什么,什么时候是一个好方法?

ruby-on-rails - RubyGems 安装错误的代码

ruby 轨道 : Can you put Ruby code in a YAML config file?