ruby元编程的动态代理的说明中有一个例子,是说明如何用delegate类如何快速创建一个动态代理的。
动态代理的功能是将对象不认识的方法转发给封装它的Assistant类做处理
先看看原来的例子
require 'delegate'
class Assistant
def initialize(name)
@name = name
end
def read_email
puts "(#{@name}) It's mostly spam!"
end
def check_schedule
puts "(#{@name})You have a meeting today!"
end
end
class Manager < DelegateClass(Assistant)
def initialze(assistant)
super(assistant)
end
def attend_meeting
puts "please hold my calls"
end
end
frank = Assistant.new("Frank")
frank.check_schedule
frank.read_email
anne = Manager.new(frank)
anne.attend_meeting
anne.read_email
anne.check_schedule
#结果输出
(Frank)You have a meeting today!
(Frank) It's mostly spam!
please hold my calls
(Frank) It's mostly spam!
(Frank)You have a meeting today!
看这个例子的过程中产生了一个疑问,这个例子中的动态代理和继承有什么区别?
这里直接如果类Manger直接继承Assistant的话,也能在这种情况下,直接调用到父类的read_email,check_schedule方法。为什么一定要通过
delegate来创建呢?
修改了下源码,让Manger继承Assistant。比较下输出
(Frank)You have a meeting today!
(Frank) It's mostly spam!
please hold my calls
(#<Assistant:0x31788bc>) It's mostly spam!
(#<Assistant:0x31788bc>)You have a meeting today!
可以发现,这里name参数的位置,在Manger对象的情况下,输出的是类实例,对象。所以,个人理解这里使用代理场景的意义在于,“代理”这个词
这里是将当前Manger对象需要处理的内容完全交给了Assistant类的对象处理,包括使用的成员参数等,实际上做出处理的是Assistant类对象。
如果是继承,则处理主体还是Manger。
修改定义对象的方式
anne = Manager.new("Frank")
anne.attend_meeting
anne.read_email
anne.check_schedule
rubytest.rb:37: undefined method `read_email' for "Frank":String (NoMethodError)
please hold my calls
发现找不到对应的方法,这种情况在继承方式中是不会出现的。
但是在动态代理中显然不行,需要在定义Manger类对象时,给出Assistant对象作为入参,这样才能在Method_miss的时候找到对应的方法