代码之家  ›  专栏  ›  技术社区  ›  Topher Fangio

从别名方法调用super

  •  1
  • Topher Fangio  · 技术社区  · 16 年前

    我试图让我的代码干涸一点,所以我正在编写一个方法来推迟或委托某些方法到另一个对象,但前提是它存在。这是一个基本的想法:我有 Shipment < AbstractShipment 可能有一个 Reroute < AbstractShipment . 要么是 Shipment 或者是 Reroute 可以有 Delivery (或交货),但不能同时交货。

    当我调用shipment.deliveries时,我希望它先检查一下是否有重新路由。如果没有,只需打电话 AbstractShipment deliveries 方法;如果是,则将该方法委托给重新路由。

    我用下面的简单代码进行了尝试:

    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_方法只是一个方便的方法,可以找出调用了哪个方法。但是,打电话 super 投掷

    super: no superclass method `deferToReroute'
    

    我搜索了一下,发现 this link 它讨论了这是Ruby1.8中的一个bug,但在1.9中得到了修复。不幸的是,我还不能将此代码升级到1.9,所以有人对解决方法有什么建议吗?

    谢谢:

    编辑: 在看了一会儿我的代码之后,我意识到我实际上不需要为我所做的所有方法都加别名,实际上我只需要覆盖deliveries方法,因为其他三个方法实际上调用它进行计算。不过,我还是很想知道你们的想法,因为我以前遇到过这种情况。

    1 回复  |  直到 16 年前
        1
  •  2
  •   austinfromboston    16 年前

    与其在这里使用alias_方法,不如硬重写这些方法,比如:

    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
    

    使用直接评估报价 good performance characteristics 并且允许您为在类定义中所做的事情使用简单的声明性语法。