Ruby 《Ruby 元编程》读书笔记 (二)

lazybios · 2015年09月09日 · 最后由 lazybios 回复于 2016年06月26日 · 4100 次阅读

继续昨天的主题

博客地址 :《Ruby 元编程》读书笔记 (二)

相关文章:

《Ruby 元编程》读书笔记 (一) 《Ruby 元编程》读书笔记 (三) 《Ruby 元编程》读书笔记 (四) 《Ruby 元编程》读书笔记 (五)

头图还是它↓↓↓

Ruby元编程

动态方法

动态调用方法

在 Ruby 中通过 Object#send 方法可以代替点标识调用对象的指定实例方法

示例代码

class MyClass
    def my_method(my_arg)
        my_arg * 2
    end
end

obj = MyClass.new
obj.my_method(3)    #=> 6
obj.send(:my_method, 3) #=> 6

上面代码通过直接调用和使用 send 方法调用得到的结果是一样的,使用 send 的好处是,可以在编码中,动态的决定方法调用。这个技巧在元编程中被称为动态派发

另外需要指出的地方是通过 Object#send 不仅可以调用公共方法,也可以调用对象的私有方法。如果想保留对象的封装特性,不向外暴露私有方法可以使用 Object#public_send 方法。

动态定义方法

除了方法的动态调用之外,Ruby 还通过 Module#define_method 方法和代码块提供了动态方法定义方式

示例代码

class MyClass
    define_method :my_method do |my_arg|
        my_arg * 3
    do
end

obj = MyClass.new
obj.my_method(2)  #=> 6

上面代码通过 define_method 方法取代了关键词 def,其本质上都是相同的,只是在定义方式上,define_method 的方式更加灵活一些,可以通过在编码中通过推导,完成函数的定义,增加了实现的灵活性。

method_missing 方法

严格意义上将 method_missing 方法,并不算是明确的定义 (不会出现在 methods 列表中),其本质是通过方法查找的机制来截获调用信息进而合理的给出相应方法的回应。有点类似与异常处理中的抛出异常,一层一层的往外抛。

method_missing 利用的机制是,当一个对象进行某个方法调用的时候,会到其对应的类的实例方法中进行查找,如果没有找到,则顺着祖先链向上查找,直到找到 BasicObject 类为止。如果都没有则会最终调用一个 BasicObject#method_missing 抛出 NoMethodError 异常。

当我们需要定义很多相似的方法时候,可以通过重写 method_missing 方法,对相似的方法进行统一做出回应,这样一来其行为就类似与调用定义过的方法一样。

示例代码

class Roulette
  def method_missing(name, *args)
    person = name.to_s.capitalize
    super unless %w[Bob Frank Bill Honda Eric].include? person
    number = 0
    3.times do
      number = rand(10) + 1
      puts "#{number}..."
    end
    "#{person} got a #{number}"
  end
end

number_of = Roulette.new
puts number_of.bob
puts number_of.kitty

动态代理

对一些封装过的对象,通过 method_missing 方法收集调用,并把这些调用转发到被封装的对象,这一过程称为动态代理,其中 method_missing 体现了动态,转发体现了代理

const_missing 方法

与 method_missing 类似,还有关于常量的 const_missing 方法,当引用一个不存在的常量时,Ruby 会把这个常量名作为一个符号传递给 const_missing 方法。

白板类 (blank slates)

拥有极少方法的类称为白板类,通过继承 BasicObject 类,可以迅速的得到一个白板类。除了这种方法以外,还可以通过删除方法来将一个普通类变为白板类。

删除方法

删除某个方法有两种方式:

  • Module#undef_method
  • Module#remove_method

二者的区别是 Module#undef_method 会删除所有 (包括继承而来的) 方法。而 Module#remove_method 只删除接受者自己的方法,而保留继承来的方法。

动态方法与 Method_missing 的使用原则

当可以使用动态方法时候,尽量使用动态方法。除非必须使用 method_missing 方法 (方法特别多的情况),否则尽量少使用它。

-待续-

=============== 最后贴一下自己的公众账号

可以十日不将军,不可一日不拱卒,日拱一卒 (rigongyizu365)

共收到 7 条回复

很有深度,条理清晰。:plus1:

期待续集,

最近在读元编程第二版, 贴一个元编程的例子

class Algo
  def method_missing(method_name,*args)
    op="*" if method_name==:multiply
    op="+" if method_name==:add ## method name is a symbol
    op="/" if method_name==:divide
    op="-" if method_name==:minus
    super.method_missing(method_name,*args) if not op
    args.inject(:"#{op}")
  end
end

obj=Algo.new
p obj.add(1,2,3,4)
p obj.multiply(1,2,3,4)
p obj.take(1,2,3,4)

#3 楼 @arth :plus1: 话说以前还见过这么一道面试题

喜欢元编程这本书,有机会一定要读读第二版。

const_missing 有没有实例, 求分享。

喜欢,有机会一定要读读

lazybios 《Ruby 元编程》读书笔记 (十六)[连载完结] 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (一) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (三) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (四) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (五) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (六) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (七) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (八) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (九) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十一) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十二) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十三) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十四) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十五) 中提及了此贴 06月26日 10:50
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册