新手问题 给已存在的类添加类方法和实例方法

spfzzz · 2018年11月07日 · 最后由 IDbbnn345 回复于 2018年11月18日 · 3003 次阅读

《Ruby 的原理解析》里有记载:

1.每个 Ruby 对象都是类指针和实例变量数组的组合。 2.Ruby 类是包含方法定义、属性名称、超类指针和常量表的 Ruby 对象。

今天参加了面试,虽然 out 了,还是做点记录吧。。。给类添加实例方法和类方法的方式有很多种,不知道面试官为什么对已存在的类情有独钟??? 也就是说,类的对象只保存了 self 指针和对象中的实例变量值的数组(或者是散列表:实例变量名为键,实例变量为值);类的实例方法是保存在类中的(底层是 C 语言实现的 RClass)。

  • 那么 Ruby 的类方法是保存在哪呢?

答案是类的单例类中。

也就是说,将方法添加到类的单例类中,就等于给类添加了类的方法;把方法添加到类中,就是添加了实例方法。

class Storage
end

module Methods
  def abc
    puts self
    "abc_methods"
  end
end
Storage.singleton_class.class_eval do
  include Methods
end
Storage.class_eval do
  include Methods
end

代码中的 puts self 的输出证明方法已经是类方法或者是实例方法了。

至于 Ruby 为什么要把类方法单独放在单例类中,这样做有什么好处就不清楚了。难道是因为类中保存的东西太多,把类方法分离出去放在单例类中减少使用的内存吗?

你没有见 rails 对现有 string date time 类做了大量扩展吗

平时自定义的类当然是 Class 的对象,这里说的 Ruby 对象偏向于指自定义类 new 出来的对象,同时也包括自定义类;对象里面保存类的指针和实例变量的值的数组。自定义类有两个身份:类和对象。

zouyu 回复

非常感谢提醒,刚翻看了很久没看的《Ruby 元编程》一书,才回想起来 class 关键字的含义

zouyu 回复

但是还是不明白,Ruby 为什么要把类方法单独放在单例类中,这样做有什么好处?

spfzzz 回复

语言就是这么设计的

Storage.singleton_class.class_eval来定义类方法挺繁琐的,在项目中一般直接用Storage.instance_eval或者在类中用class<<self打开单例类

spfzzz 回复

我们可以参考一下 Java 的静态类方法…… 它其实还是通过单例类实现的,只是给你隐藏了而已。

Ruby 只是不做那个没必要的折腾

spfzzz 回复

参考 Metaprogramming Ruby 2nd > chapter 5 > Singleton Classes > Singleton Classes and Inheritance:

Why does Ruby go to such lengths to organize the object model this way? The reason is that thanks to this arrangement, you can call a class method on a subclass:

D.a_class_method # => "C.a_class_method()"

Even if a_class_method is defined on C , you can also call it on D

这问题感觉像是 无二之旅的面试官风格😀

有兴趣了解一下 scope 方法的实现方式么😀

需要 登录 后方可回复, 如果你还没有账号请 注册新账号