Ruby 中的 module_function 和 extend self异同

 更新时间:2017年05月23日 08:49:03   作者:hww_面条酱  
本文主要给大家介绍了在Ruby中 module_function 和 extend self的共同点和区别,非常的详细,也很实用,方便大家更好的理解的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, but can be call as module_name.module_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, if the module is included to a class , 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, for object, module method is private instance method"

总结就是

•The method will be copied to class' singleton class
•The instance method's visibility will become private

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, included by a class"
"a private method, can be call in module internal"
"private method can not be called by object.private_method"

总结就是:
•No method copying involved
•No changes to method visibility

总结

module_function 改变 module 内 原来 method 的 public/private 属性并把改 method 变成 module method ,能够被 module_name.module_method 调用。

extend self 就是在 module 自继承,不改变 module 中 method 的 public/private 属性,能够被 module_name.public_method

相关文章

  • Ruby最简单的消息服务器代码

    Ruby最简单的消息服务器代码

    这篇文章主要介绍了Ruby最简单的消息服务器,大家参考使用
    2013-11-11
  • rails 连接mysql的问题解决

    rails 连接mysql的问题解决

    如果是先安装ruby 和rails,后安装mysql,可能会出现如下错误
    2008-12-12
  • Ruby基础知识之基本流程控制

    Ruby基础知识之基本流程控制

    这篇文章主要介绍了Ruby基础知识之基本流程控制,本文讲解了条件判断、循环语句、迭代器和枚举三部分内容,需要的朋友可以参考下
    2015-04-04
  • 深入理解Ruby中的代码块block特性

    深入理解Ruby中的代码块block特性

    听到代码块这个翻译,你或许会联想到类或者结构体,但block并不是这些东西,这里就带着大家来深入理解Ruby中的代码块block特性
    2016-05-05
  • 使用C++来编写Ruby程序扩展的教程

    使用C++来编写Ruby程序扩展的教程

    这篇文章主要介绍了使用C++来编写Ruby程序扩展的教程,本文来自于IBM官方网站技术文档,需要的朋友可以参考下
    2015-04-04
  • 初步讲解Ruby编程中的多线程

    初步讲解Ruby编程中的多线程

    这篇文章主要介绍了初步讲解Ruby编程中的多线程,线程是各种编程语言学习当中的重点和难点,需要的朋友可以参考下
    2015-04-04
  • Ruby优化继承类实例

    Ruby优化继承类实例

    这篇文章主要介绍了Ruby优化继承类实例,本文直接给出一个优化实例及实现代码,需要的朋友可以参考下
    2015-05-05
  • 收集的多个ruby遍历文件夹代码实例

    收集的多个ruby遍历文件夹代码实例

    这篇文章主要介绍了收集的多个ruby遍历文件夹代码实例,本文总结了4个代码片段,小编推荐最后一个方法,因为它很简洁优雅,需要的朋友可以参考下
    2015-05-05
  • rails创建应用程序实例

    rails创建应用程序实例

    这篇文章主要介绍了rails创建应用程序实例,本文从零开始教你完成一个rails网站应用的创建过程,需要的朋友可以参考下
    2014-06-06
  • Ruby中任务构建工具rake的入门学习教程

    Ruby中任务构建工具rake的入门学习教程

    这篇文章主要介绍了Ruby中任务构建工具rake的入门学习教程,讲解了包括命名空间和默认任务的执行等基础知识,需要的朋友可以参考下
    2016-03-03

最新评论