Ruby 如何理解 Module 类里面的 module methods

runup · 2016年01月07日 · 最后由 imconfused 回复于 2016年01月25日 · 3342 次阅读

在使用 define_method 方法的过程中,经常会感觉到疑惑,因此下面做一个总结。

  • define_method 的一般用法
#下面的代码直接在类中使用define_method方法定义:test的类
class Test
  define_method :test do
    puts "this is the define_method demo"
  end
end

obj = Test.new
obj.test #=>"this is the define_method demo"

最初的疑惑是为什么可以在类中直接使用 define_method 方法,然后以为的解释是实现了 module_funciton 的功能,module_functon 主要实现了下面的两个功能,代码如下所示:

#模块名.方法名直接调用
Kernel.puts "this is the test"
#类似于关键字在程序的任何部分进行调用
puts "this is the test"

但是其实,上面的解释是合理,因为在 define_method 不能实现上面的两个功能,即不能实现 Module.define_method 功能,也不能随意在程序块内直接使用 define_method 功能。

  • define_method 是 Module 类私有实例方法,同时 Module 类是 Class 类的父类,因此 define_method 做为一般类对象的类方法被直接调用。代码演示如下:
irb: Module.private_instance_method.grep(/define_method/)
irb: [:define_method]

class Module
  def demo
    puts "this is the demo"
  end

  private :demo
end

class Test
  #self.demo是要报错的,但是如果没有private标示符,self和self.demo都是可以的。
  demo
end

不得不说你把本来就不好懂的问题,描述得更不好懂了

#1 楼 @qinfanpeng 我自己有点被绕了,描述问题的时候想了很久,但是发现自己却没有能力把问题描述清楚。

可以看出 module_functionprivate 都是 Module 类的实例方法。但是:

Module.methods.grep /^priva/
=> [:private_instance_methods,
 :private_constant,
 :private_method_defined?,
 :private_class_method,
 :private_methods]

Module.methods.grep /^mod/
=> [:module_exec, :module_eval]

其中原因暂时不知,若知晓,勿忘告知。

很难说用了 Module 类中那些方法实现了 module_funciton 功能,因为 module_funciton 是用 C 语言来写的,并没有调用其他方法。基本上这个 C 函数就是检查参数,查找参数里的方法名在 module 中是否存在。然后用这一句

rb_method_entry_set(rb_singleton_class(module), id, me, METHOD_VISI_PUBLIC);

将这个 instance_method 注册为 class_method。所以说 define_method 和 instance_method 两者互相独立,不存在相互调用关系,而且两者的功能完全不一样。define_method 是直接定义方法,而 module_funciton 是将本来在 module 里的 instance_method 绑定为 class_method,好通过 Module 名直接调用。

楼主为什么会觉得

在以上的代码中 define_method 方法实现 module function 的功能

#5 楼 @reyesyang 写出这句话的时候,我心里也是非常疑虑,不过似乎只有人为它实现了 module function 的功能,才能解释它在这里的用法,被对象隐式调用。

#3 楼 @qinfanpeng 貌似大家在这个地方都有很多不是很明了的地方,是不是因为缺乏对最底层 C 的知识的掌握?

#4 楼 @adamshen 读了很多遍,不甚理解,待我把元编程的书翻完,再来看您的解释。

#3 楼 @qinfanpeng 另外问,您的这个图是什么工具?

#7 楼 @runup 感觉还没到 C 语言那一块,更多的是其实现细节这些吧

irb(main):001:0> Module.class
=> Class
irb(main):002:0> Class.class
=> Class
irb(main):003:0> Class.superclass
=> Module
irb(main):004:0> Module.superclass
=> Object
irb(main):005:0> Class.superclass.superclass

#13 楼 @imconfused 其实不太明白。

就是说 Class 的超类是 Module

#3 楼 @qinfanpeng 请教别的问题。好奇的问下,为啥我在http://api.rubyonrails.org/ 中搜索 mo 跟你这个结果不一致呀。是不是有啥门道?而且我的下面也没有实例方法。谢谢。

17 楼 已删除

#16 楼 @torubylist 你要找的话也该是看 Ruby 的 API,而非 Rails 的。

21 楼 已删除

#20 楼 @qinfanpeng 感谢。已装 dash。神器。

#13 楼 @imconfused 回过头来看,有点明白了,但是这里的话,Modulel 类是 Class 类的父类,那么 Module 类的实例方法被 Class 类继承,因此 Module 类的实例方法可以作为普通类的类方法进行直接调用。但是,Object 是 Module 的父类,Module 是 Class 的父类,那么 Object 是 Class 类的间接父类,那么为什么 Object 类的实例方法没有成为普通类的类方法? 也请教下您@qinfanpeng

#23 楼 @runup 自己用irb多试试看,对于ruby的继承链有点多的了解了以后再思考这些比较细致的问题,多看看Ruby元编程,我自己也前前后后翻了 3 遍,但是对于有些概念还是摸不透,也要用irb来验证自己的想法

irb(main):033:0> BasicObject.instance_methods.join ','
"==,equal?,!,!=,instance_eval,instance_exec,__send__,__id__"
irb(main):034:0> Object.instance_methods(false).join ','
"methods,private_methods,protected_methods,public_methods,singleton_methods"
irb(main):035:0> Kernel.instance_methods(false).join ','
"nil?,===,=~,!~,eql?,hash,<=>,class,singleton_class,clone,dup,itself,taint,tainted?,untaint,untrust,untrusted?,trust,freeze,frozen?,to_s,inspect,methods,singleton_methods,protected_methods,private_methods,public_methods,instance_variables,instance_variable_get,instance_variable_set,instance_variable_defined?,remove_instance_variable,instance_of?,kind_of?,is_a?,tap,send,public_send,respond_to?,extend,display,method,public_method,singleton_method,define_singleton_method,object_id,to_enum,enum_for,ai,awesome_inspect,awesome_print"
irb(main):036:0> Class.instance_methods(false).join ','
"allocate,new,superclass,instance_methods,private_instance_methods,protected_instance_methods,public_instance_methods"
irb(main):037:0> Module.instance_methods(false).join ','
"freeze,===,==,<=>,<,<=,>,>=,to_s,inspect,included_modules,include?,name,ancestors,instance_methods,public_instance_methods,protected_instance_methods,private_instance_methods,constants,const_get,const_set,const_defined?,const_missing,class_variables,remove_class_variable,class_variable_get,class_variable_set,class_variable_defined?,public_constant,private_constant,singleton_class?,include,prepend,module_exec,class_exec,module_eval,class_eval,method_defined?,public_method_defined?,private_method_defined?,protected_method_defined?,public_class_method,private_class_method,autoload,autoload?,instance_method,public_instance_method"
irb(main):038:0> class A
irb(main):039:1> end
nil
irb(main):040:0> A.ancestors
[
    [0] A < Object,
    [1] Object < BasicObject,
    [2] Kernel,
    [3] BasicObject
]
需要 登录 后方可回复, 如果你还没有账号请 注册新账号