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, 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 on Rails实现最基本的用户注册和登录功能的教程
这里我们主要以has_secure_password的用户密码验证功能为中心,来讲解Ruby on Rails实现最基本的用户注册和登录功能的教程,需要的朋友可以参考下...2020-06-30- 二分查找是一种在已经过排序的数组中搜索指定元素用的算法,这里我们就来看一下Ruby实现二分搜索(二分查找)算法的简单示例:...2020-06-30
- Ruby将字符串像数字一样处理.我们用单引号('...')或双引号("...")将它们括起来. ruby> "abc" "abc" ruby> 'abc' "abc" 单引号和双引号在某些情况下有不同的...2020-06-30
- Rack是一个连接Ruby程序与服务器程序之间的中间件,甚至可以说Rails也是在Rack的基础上建立起来的,这里我们就来为大家带来Ruby on Rails中Rack中间件的基础学习教程...2020-06-30
- 钩子方法即是在普通的方法上添加"钩子",使特定事件发生时可以被调用,下面就来以实例讲解Ruby中的钩子方法及对方法调用添加钩子...2020-06-30
- 单件方法顾名思义,就是只作用于单个对象的方法,同理单件类就是单件方法所存在的类,规定其作用域,这里我们就来详解Ruby中的单件方法和单件类:...2020-06-30
- gem是一种文件组织的包,一般的ruby的很多插件都有由这种各种的包提供。我们来看看gem的用法...2020-06-30
Ubuntu上配置Ruby on Rails框架及RubyMine IDE开发环境
Ruby on Rails是Ruby世界中当仁不让的Web框架代表,甚至可以说Rails推动了Ruby的流行,这里我们就来看一下如何在Ubuntu上配置Ruby on Rails框架及RubyMine IDE开发环境...2020-06-30Ruby 中的 module_function 和 extend self异同
本文主要给大家介绍了在Ruby中 module_function 和 extend self的共同点和区别,非常的详细,也很实用,方便大家更好的理解的module_function 和 extend self...2020-06-30Ruby on rails安装后去掉DL is deprecated,please use Fiddle警告信息的方法【测试可用】
这篇文章主要介绍了Ruby on rails安装后去掉DL is deprecated,please use Fiddle警告信息的方法,通过针对Ruby on rails安装文件中的警告部分源码进行注释来达到消除警告的目的,需要的朋友可以参考下...2020-06-30SignalR Self Host+MVC等多端消息推送服务(三)
这篇文章主要为大家详细介绍了SignalR Self Host+MVC等多端消息推送服务的第三篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22- 这篇文章主要介绍了ruby ftp封装实例详解的相关资料,需要的朋友可以参考下...2020-06-30
- 插入排序即是把已有的有序序列从后向前扫描插入元素,数值大的向后移动,这里我们就来看一下使用Ruby实现插入排序算法及进阶的二路插入排序代码示例...2020-06-30
- Hash类型在Ruby中就相当于Python的字典,是一个键值对应的集合类型,这里就来整理一下Ruby中的Hash哈希类型基本操作方法小结:...2020-06-30
.NET Core 1.0创建Self-Contained控制台应用
这篇文章主要为大家详细介绍了.NET Core 1.0创建Self-Contained控制台应用的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22Ruby rails 页面跳转(render和redirect_to)
今天在做R.R.log的时候发现个问题,在修改密码的时候如果没有通过校验,没有显示校验错误的信息。...2020-06-30- 在本篇文章里小编给大家分享了关于Ruby创建数组方法的知识点内容,对戏有兴趣的朋友们学习下。...2020-06-25
- 这篇文章主要介绍了C#实现Ruby的负数索引器的相关代码和使用方法,非常简单实用,需要的朋友可以参考下...2020-06-25
win10下使用virtualbox + vagrant配置ruby开发机环境
Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境。它 使用Oracle的开源VirtualBox虚拟化系统,使用 Chef创建自动化虚拟环境。搭配Cmder如丝般顺滑,实现你所有关于Mac&Linux的幻想...2020-06-30- Rails项目通过Ruby世界中的gem和rake工具来构建起来真的相当方便,这里就给大家整理了一份Ruby on Rails网站项目构建简单指南,需要的朋友可以参考下...2020-06-30