Ruby 中的 module_function 和 extend self异同
在阅读开源的 Ruby 代码和编写可维护性的代码经常遇到这两者的使用,那么他们两者的共同点和区别是什么呢? module_function Ruby 的 module 是 method 和 constants 的集合。module 中的method 又可分为 instance method 和 module method,当一个 module 被 include 进一个 class,那么 module 中的 method (注:没有被 module_function 标记的 method)就是 class 中的 instance method,instance method 需要所在的 class 被实例化之后才能被调用;被 module_function 标记的 method(不管该 method 是 public 或者 private)就是 module method 且 instance method 也会变成 private method,对于被 include 所在的 class 来说是 private method,object.module_name 会出错。module method 都能被 module_name.method_name 调用,没有被 module_function 标记的 public method 不能被 module_name.method_name 调用。 module 中的 module_function 会把 module 中的 method 变成 module method 且对于被 include 所在的 class 来说,module method 在 module 中是 private method 故 module_name.module_method 能调用,而不能被 object.module_name 调用。 module 中的 public method 对于被 include 所在的 class 来说是 instance method,故 object.public_method_in_module 能调用。如果想要非 module method 能够被 module 调用(module_name.not_module_method) ,需要引入 extend self (下文会讨论 extend self) # test.rb module MyModule def public_meth p "a public method,if the module is included to a class,can be call as object.public_meth" end def module_method p "a module method,can be called as module_name.module_method. but can not be call as object.module_method" end private def private_method_to_module_function p "a private_method,but can be call as module_name.module_method,because it was assigned to module_function" end def private_method p "I am a private method" end module_function :module_method,:private_method_to_module_function end MyModule.module_method MyModule.private_method_to_module_function begin MyModule.public_meth rescue p "public method can not be called by module_name.public_meth" end begin MyModule.private_method rescue NoMethodError p "private method can not be called by module_name.module_method" end class MyClass include MyModule end obj = MyClass.new obj.public_meth begin obj.private_method rescue NoMethodError p "private method in module can not be call by object.method_name" end begin obj.module_method rescue NoMethodError p "module method can not be called by object.method_name,for object,module method is private instance method" end #调用 ruby test.rb "a module method,can be called as module_name.module_method. but can not be call as object.module_method" "a private_method,because it was assigned to module_function" "public method can not be called by module_name.public_meth" "private method can not be called by module_name.module_method" "a public method,can be call as object.public_meth" "private method in module can not be call by object.method_name" "module method can not be called by object.method_name,module method is private instance method" 总结就是 •The method will be copied to class' singleton class extend self Include is for adding methods to an instance of a class and extend is for adding class methods extend 本质是给 class 或者 module 添加 class method extend self 让 module 中的 instance method 能够被 module_name.instance_method 调用,保留 module 中原本 method 的 public 或 private 属性,但又不像 module_function 一样把被标记的 method 变成 private 。 #!/usr/bin/env ruby # encoding: utf-8 # test_extend.rb module MyModule extend self def public_meth p "a public_method extended by self can be called by module_name.public_meth and object.public_meth,included by a class" private_method end private def private_method p "a private method,can be call in module internal" end end class MyClass include MyModule end MyModule.public_meth begin MyModule.private_method rescue NoMethodError p "private method in extend self module can not be called module_name.private_method" end obj = MyClass.new obj.public_meth begin obj.private_method rescue NoMethodError p "private method can not be called by object.private_method" end # 调用 ruby test_extend.rb "a public_method extended by self can be called by module_name.public_meth and object.public_meth,included by a class" "a private method,can be call in module internal" "private method in extend self module can not be called module_name.private_method" "a public_method extended by self can be called by module_name.public_meth and object.public_meth,can be call in module internal" "private method can not be called by object.private_method" 总结就是: 总结 module_function 改变 module 内 原来 method 的 public/private 属性并把改 method 变成 module method,能够被 module_name.module_method 调用。 extend self 就是在 module 自继承,不改变 module 中 method 的 public/private 属性,能够被 module_name.public_method (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |