译:Ruby动态方法
2017-01-14 21:29
323 查看
通常情况下,我们使用关键字def来定义方法。
但是当有一系列方法具有相同的结构和逻辑时,继续这样做未免显得有些重复并且违反了DRY原则。
Ruby,作为一个动态语言,允许你在运行时定义方法。
那么,这是什么意思呢?
来看一个最简单的例子:
define_method 用来定义实例方法,下面的例子展示更加贴合实际的使用场景。
使用动态方法定义重构:
我们使用了define_method来动态的定义方法。
我们也可以使用类方法来定义实例方法,利用这一点我们可以暴露一个用来生成实例方法的类方法。COOL!
例如:
定义类方法最简单的方式则为:
也可以使用 instance_eval和class_eval来动态定义方法。这些方法允许运行特定类或方法中的任意代码。这些方法有时候很让人迷惑,你可以看看 stackoverflow上的讨论或者读读博客来理解它们的用法。
stackoverflow上的讨论我们可以总结如下:
注意,我们没有在_eval中使用*define_method,因为如下例所示,不管在class_eval还是instance_eval内使用define_method方法,它最终定义的都是实例方法。
接下来,我们来看看方法的动态调用。Ruby中一个动态调用方法的方式是向对象发送消息。我们可以向类或类定义本身发送消息发送消息,或者只是发送给类对象。这些都可以通过调用send方法完成。
最简单的例子如下:
这个方法在什么时候有用呢?
来看看下面这段代码(取例自:http://www.funonrails.com/2011/12/dynamic-methods-inside-ruby-classes.html)
使用send方法重构:
动态方法定义能够减少方法定义的错误,减少重复并且简化代码
享受元编程吧~
原文:http://rohitrox.github.io/2013/07/02/ruby-dynamic-methods/
但是当有一系列方法具有相同的结构和逻辑时,继续这样做未免显得有些重复并且违反了DRY原则。
Ruby,作为一个动态语言,允许你在运行时定义方法。
那么,这是什么意思呢?
来看一个最简单的例子:
class A define_method :a do puts "hello" end define_method :greeting do |message| puts message end end A.new.a #=> hello A.new.greeting 'Ram ram' #=> Ram ram
define_method 用来定义实例方法,下面的例子展示更加贴合实际的使用场景。
class User ACTIVE = 0 INACTIVE = 1 PENDING = 2 attr_accessor :status def active? status == ACTIVE end def inactive? status == User::INACTIVE end def pending? status == User::PENDING end end user = User.new user.status = 1 user.inactive? #=> true user.active? #=> false
使用动态方法定义重构:
class User ACTIVE = 0 INACTIVE = 1 PENDING = 2 attr_accessor :status [:active, :inactive, :pending].each do |method| define_method “#{method}?” do status == User.const_get(method.upcase) end end end user = User.new user.status = 1 user.inactive? #=> true user.active? #=> false
我们使用了define_method来动态的定义方法。
我们也可以使用类方法来定义实例方法,利用这一点我们可以暴露一个用来生成实例方法的类方法。COOL!
例如:
class User ACTIVE = 0 INACTIVE = 1 PENDING = 2 attr_accessor :status def self.states(*args) args.each do |arg| define_method “#{arg}?” do self.status == User.const_get(arg.upcase) end end end states :active, :inactive, :pending end
定义类方法最简单的方式则为:
class A class << self define_method method_name do #... end end end
也可以使用 instance_eval和class_eval来动态定义方法。这些方法允许运行特定类或方法中的任意代码。这些方法有时候很让人迷惑,你可以看看 stackoverflow上的讨论或者读读博客来理解它们的用法。
stackoverflow上的讨论我们可以总结如下:
Foo = Class.new Foo.class_eval do def class_bar “class_bar” end end Foo.instance_eval do def instance_bar “instance_bar” end end Foo.class_bar #=> undefined method ‘class_bar’ for Foo:Class Foo.new.class_bar #=> “class_bar” Foo.instance_bar #=> “instance_bar” Foo.new.instance_bar #=> undefined method ‘instance_bar’ for #<Foo:0x7dce8>
注意,我们没有在_eval中使用*define_method,因为如下例所示,不管在class_eval还是instance_eval内使用define_method方法,它最终定义的都是实例方法。
Foo = Class.new Foo.class_eval do define_method “class_bar” do “class_bar” end end Foo.instance_eval do define_method “instance_bar” do “instance_bar” end end Foo.class_bar #=> undefined Foo.new.class_bar #=> “class_bar” Foo.instance_bar #=> undefined Foo.new.instance_bar #=> “instance_bar”
接下来,我们来看看方法的动态调用。Ruby中一个动态调用方法的方式是向对象发送消息。我们可以向类或类定义本身发送消息发送消息,或者只是发送给类对象。这些都可以通过调用send方法完成。
最简单的例子如下:
s= “hi man” p s.length #=> 6 p s.include? “hi” #=> true p s.send(:length) #=> 6 p s.send(:include?,”hi”) #=> true
这个方法在什么时候有用呢?
来看看下面这段代码(取例自:http://www.funonrails.com/2011/12/dynamic-methods-inside-ruby-classes.html)
class ApplicationController < ActionController::Base protect_from_forgery helper_method :current_staff, :current_employee, current_admin def authenticate_staff!(opts={}) current_staff || not_authorized end def current_staff current_user if current_user.is_a? Staff end def authenticate_employee!(opts={}) current_employee || not_authorized end def current_employee current_user if current_user.is_a? Employee end def authenticate_admin!(opts={}) current_admin || not_authorized end def current_admin current_user if current_user.is_a? Admin end end
使用send方法重构:
%w(Staff Employee Admin).each do |k| define_method “current_#{k.underscore}” do current_user if current_user.is_a?(k.constantize) end define_method “authenticate_#{k.underscore}!” do |opts={}| send(“current_#{k.underscore}”) || not_authorized end end
动态方法定义能够减少方法定义的错误,减少重复并且简化代码
享受元编程吧~
原文:http://rohitrox.github.io/2013/07/02/ruby-dynamic-methods/
相关文章推荐
- 红宝石(Ruby)史话
- Ruby简明教程之循环语句介绍
- ruby 一些简单的例子
- Ruby on Rails在Ping ++ 平台实现支付
- Ruby 之 class 中的 private、 protected、public
- Ruby中操作文件的方法介绍
- 详解Ruby中的单件方法和单件类
- Ruby中的集合编写指南
- CentOS 6.3下编译安装Ruby 2.0笔记
- Ruby基本的环境变量设置以及常用解释器命令介绍
- 详解Ruby中的代码块及其参数传递
- Ruby编程中关于中断和返回的用法教程
- Ruby中的异常处理代码编写示例
- Ruby程序中发送基于HTTP协议的请求的简单示例
- Ruby中的变量学习总结
- 几个加速Ruby on Rails的编程技巧
- Ruby配置rspec和RestClient来检测服务器
- 分析Cache 在 Ruby China 里面的应用情况
- Ruby中数组的一些相关使用方法