为什么在ruby中创建元类?

我试图了解 Ruby对象模型.我了解到,实例方法保存在类中而不是类的对象中,因为它会删除冗余.我读到,每当创建一个类时,也为新创建的类创建一个元类.元类存储类方法.即类的单例方法位于元类中.例如
class MyClass
  def hi
    'hi object'
  end

  def self.bye
    'bye singleton method'
  end
end

对于上述MyClass,也创建了一个元类(比如#MyClass).现在方法’hi’是一个实例级方法,可以在MyClass的所有对象上调用.方法’bye’是MyClass的单​​例方法,它位于#MyClass中.原因(我想是这样)为什么’嗨’保存在MyClass中,而不是MyClass的所有对象都是因为它避免了冗余.但是我们不能有多个名为MyClass的类.所以为什么不在MyClass中存储’再见’而不是#MyClass,因为我们不能有多个MyClass.我绝对不知道为什么这是它的方式,我只是想了解它背后的原因.

—– UPDATE —-

元类存储类信息,如单例方法等.但是,由于类是一个单例对象(它是类的一个实例,并且它的类型独立),那么为什么不将所有的信息保存在类本身而不是元​​类.

解决方法

只是为了超级明星.

这是一个快速的ruby脚本,解释这个问题:

#!/usr/bin/env ruby
puts ObjectSpace.count_objects[:T_CLASS] #>> 471
class X
  def self.foo
  end
  def bar
  end
end
puts ObjectSpace.count_objects[:T_CLASS] #>> 473

这就是“ObjectSpace.count_objects [:T_CLASS]将OP计数增加2的意思.”让我们将额外的类称为X的单例类,因为这似乎是Ruby在内部调用的类.

irb> X
=> X
irb> X.singleton_class
=> <Class: X>

请注意,#foo方法是X.singleton_class的实例方法,而不是X.

irb> X.instance_methods(false)
=> [:baz]
irb> X.singleton_class.instance_methods(false)
=> [:foo]

那为什么是:foo存储在X.singleton_class而不是X?不会只有一个X吗?

我认为主要原因是一致性.考虑以下简单的实例对象的场景.

car = Car.new
def car.go_forth_and_conquer
end

正如@mikej高超的解释,这种新方法存储在汽车的单身班.

irb> car.singleton_class.instance_methods(false)
=> [:go_forth_and_conquer]

类是对象

现在,类也是对象.每个类都是Class的一个实例.因此,当定义一个类(例如X)时,ruby真的创建了一个Class的实例,然后向实例添加方法(类似于上面所提到的方法).例如,这里是另一种创建方式一个新课

Car = Class.new do
  def go_forth_and_conquer
    puts "vroom"
  end
end
Car.new.go_forth_and_conquer

因此,只需重用代码并以相同的方式进行操作就更容易了(即在X.singleton_class中保留foo).这可能需要较少的工作,并且会导致更少的惊喜,所以没有人会需要编写代码来处理类实例与其他实例不同.

可能不重要

你可能会认为,如果Ruby没有Class类的单例类,那么可以节省一些内存.然而,对我来说,实际存储的是一个实现细节,我们可能不应该指望.只要行为是一致的,Rubinius,MRI和JRuby都可以不同地存储方法和实例.对于我们所知道的,只要总体行为符合ruby规范,就可以合理地实现Ruby,它不会为类对象而急切地创建单例类. (例如,在#singleton_class方法首次被调用之前,实际的单例类不存在)

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...