2009-06-04 87 views
1

我想干掉我的代码,所以我正在编写一种方法将某些方法推迟或委托给不同的对象,但只有当它存在时。这里是基本的想法:我有Shipment < AbstractShipment可能有Reroute < AbstractShipmentShipment或它的Reroute可以有Delivery(或交付),但不是两者。从别名方法调用超级方法

当我打电话shipment.deliveries,我希望它检查,看它是否有重新路由第一。如果不是,那么只需拨打AbstractShipmentdeliveries方法;如果是,则将该方法委派给重新路由。

我试图与下面的简单代码:

module Kernel 
    private 
    def this_method 
     caller[0] =~ /`([^']*)'/ and $1 
    end   
end 

class Shipment < AbstractShipment 
    ... 

    def deferToReroute 
    if self.reroute.present? 
     self.reroute.send(this_method) 
    else 
     super 
    end 
    end 

    alias_method :isComplete?, :deferToReroute 
    alias_method :quantityReceived, :deferToReroute 
    alias_method :receiptDate, :deferToReroute 
end 

的Kernel.this_method仅仅是找出哪些方法被调用了便利。但是,调用super抛出

super: no superclass method `deferToReroute' 

我搜索了一下,发现this link其中讨论,这是Ruby 1.8中的一个错误,但固定在1.9。不幸的是,我无法将此代码升级到1.9,所以有人有任何解决方法的建议吗?

感谢:-)

编辑:后一点看我的代码,我意识到,我并不真的需要别名的所有的,我做的方法,我其实只需要覆盖交货方法,因为其他三个实际称之为他们的计算。但是,自从我遇到过这个问题之后,我仍然很想知道你们的想法。

回答

2

而不是在这里使用alias_method,你可能会得到更好的硬重写这些方法,像这样服务:

class Shipment < AbstractShipment 
    def isComplete? 
    return super unless reroute 
    reroute.isComplete? 
    end 
end 

,如果你发现你正在做的每类此的5-10倍,你可以把它更好像这样:

class Shipment < AbstractShipment 
    def self.deferred_to_reroute(*method_names) 
    method_names.each do |method_name| 
     eval "def #{method_name}; return super unless reroute; reroute.#{method_name}; end" 
    end 
    end 
    deferred_to_reroute :isComplete?, :quantityReceived, :receiptDate 
end 

使用直EVAL提供good performance characteristics,并允许你有你的类定义中做一个简单的声明语法。

+0

太棒了!如果我已经玩了一段时间了,我会尝试这样的事情,因为我一直在编写一个类似的插件,但我怀疑它会一直很干净。非常感谢 :-) – 2009-06-05 13:24:48