善用 define_method

来源:互联网 发布:怎么申请农村淘宝 编辑:程序博客网 时间:2024/06/06 12:31

define_method 可以帮助我们动态的,快速的定义多个方法;比如有这样一个类:

class Post  attr_accessor :title, :content, :state  def initialize(title, content, state = :draft)    @title, @content, @state = title, content, state  end  def draft    @state = :draft  end  def posted    @state = :posted  end  def deleted    @state = :deleted  endend

draft posted deleted 分别用来把文章的状态设置为: 草稿 发表 和 删除 ,但是这三个方法看起来太类似了,而define_method 就可以帮助我们优化这部分代码:

class Post  attr_accessor :title, :content, :state  def initialize(title, content, state = :draft)    @title, @content, @state = title, content, state  end  states = [:draft, :posted, :deleted]  states.each do |state|    define_method state do      @state = state    end  end

这下就轻松多了吧!再来一个稍微复杂一点的例子,可以体现其灵活性:

class Game  attr_accessor :name, :year, :system  SYSTEMS = ['SNES', 'PS1', 'Genesis']  SYSTEMS.each do |system|    define_method "runs_on_#{system.downcase}?" do      self.system = system.downcase    end  endend

那么,如何在目标方法之后传递参数呢?比如说代理一个 block?

class Book# 省略不相关代码  [:each, :map, :select].each do |method|    define_method method do |&block|      books.send(method, &block)    end  endend

方法体中之所以使用 send 方法,是因为在我们要重新定义的 each 方法里,books 需要委托数组方法 each 来处理 &block,而不是由 books 直接处理 █当然,其它两个方法也是这样的道理。最终 Ruby 帮我们生成的方法就是类似这样的:

def each # 这是我们为 Book 类定义的 each 方法  books.each(&block) # 这是委托数组的 each 方法来帮 books 处理传入的 &blockend
0 0
原创粉丝点击