RubyライブラリでDelegatorクラスの実装を依頼


依頼のモードの上で1篇は天を盗んで日を変えてすでに解釈して、ここは中のDelegatorライブラリの実現だけを説明します.
ルビーを採用する以上、そのライブラリは一般的に、よりfunny的で、より自然に使用されます.
singleton単例ライブラリのようにクラスを書きます

class Klass
 def method
 end
end

単一のクラスにするには:

require 'singleton'
class Klass
 include Singleton
 def method
 end
end

このように簡単で、それは自動的に構造方法を非表示にして、自動的にマルチスレッドロック呼び出しをロードして、わあ、やはりスレッドは安全で、もし自分で多くのコードを書いて、しかもrubyのModuleメカニズムを使って、いかなるクラスを継承する必要がなくて、副作用がありません...
さあ、余談が終わったら、Delegatorを見てみましょう.
rubyライブラリのdelegateを開きます.rbファイル
コード行はどれくらいありますか.いいやつです.330行ぐらいです.注釈を除いて、実際の有効コードは100行あるでしょう.
手順1インタフェースの使用方法を確認します.

# SimpleDelegator's implementation serves as a nice example here.
#
#    class SimpleDelegator < Delegator
#      def initialize(obj)
#        super             # pass obj to Delegator constructor, required
#        @_sd_obj = obj    # store obj for future use
#      end
# 
#      def __getobj__
#        @_sd_obj          # return object we are delegating to, required
#      end
# 
#      def __setobj__(obj)
#        @_sd_obj = obj    # change delegation object, a feature we're providing
#      end
# 
#      # ...
#    end

つまりDelegatorを継承して実現すればgetobj__と_setobj__方法でいいです.
この使い方は前編のすり替えでこの方法を使った.
考えてみれば、このようなインタフェースも簡潔です.
どのように実現するかを見てみましょう.

class Delegator

  #
  # Pass in the _obj_ to delegate method calls to.  All methods supported by
  # _obj_ will be delegated to.
  #
  def initialize(obj)
    #          ,    
    #  Kernel   module,        .   RubyHackGuide    .
    preserved = ::Kernel.public_instance_methods(false)
    preserved -= ["to_s","to_a","inspect","==","=~","==="]
    for t in self.class.ancestors
      preserved |= t.public_instance_methods(false)
      preserved |= t.private_instance_methods(false)
      preserved |= t.protected_instance_methods(false)
      break if t == Delegator
    end
    preserved << "singleton_method_added"
    for method in obj.methods
      #          ,
      #       eval           
      next if preserved.include? method
      begin
       #    self     ,   ,   .
       #               ,        .
       #                ,            ,     ...(   ,                   )
	eval <<-EOS
	  def self.#{method}(*args, &block)
	    begin
	      __getobj__.__send__(:#{method}, *args, &block)
	    rescue Exception
	      [email protected]_if{|s| /:in `__getobj__'$/ =~ s} #`
	      [email protected]_if{|s| /^\\(eval\\):/ =~ s}
	      Kernel::raise
	    end
	  end
	EOS
      rescue SyntaxError
        raise NameError, "invalid identifier %s" % method, caller(4)
      end
    end
  end
  alias initialize_methods initialize

  #   method_missing                    , ' '(   )      ,       .
  #        ,           ,         ...
  # Handles the magic of delegation through \_\_getobj\_\_.
  def method_missing(m, *args)
    target = self.__getobj__
    unless target.respond_to?(m)
      super(m, *args)
    end
    target.__send__(m, *args)
  end

  # 
  # Checks for a method provided by this the delegate object by fowarding the 
  # call through \_\_getobj\_\_.
  # 
  def respond_to?(m)
    return true if super
    return self.__getobj__.respond_to?(m)
  end

  #
  # This method must be overridden by subclasses and should return the object
  # method calls are being delegated to.
  #
  #            .
  def __getobj__
    raise NotImplementedError, "need to define `__getobj__'"
  end

  #         marshal       .
  #       ,      .
  # Serialization support for the object returned by \_\_getobj\_\_.
  def marshal_dump
    __getobj__
  end
  # Reinitializes delegation from a serialized object.
  def marshal_load(obj)
    initialize_methods(obj)
    __setobj__(obj)
  end
end

すべての解析は上の注釈にあります.
ここではあなたのruby技術がかなり熟練していて、ruby元のプログラミングスキルを身につける必要があります.能力が限られているので、異なる観点について検討することを歓迎します.
ここに書いたら、松本行弘さんによるとforwardableモジュールの方が優れているそうです.時間があればもう一度検討してもいいです.
最后に文句を言って、rubyライブラリのテストは完璧ではありませんて、たまにいくつかの问题が现れて、またサルのパッチを行う必要があります..