Created
December 10, 2011 16:56
-
-
Save pasberth/1455584 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| # Ruby では動的プロクシオブジェクトがよく使われます。 | |
| # 利用例は | |
| # - https://gist.github.com/1436624 | |
| # - https://gist.github.com/1263663 | |
| # - https://github.com/pasberth/Dam/blob/master/src/dam.rb | |
| # gems では lazy などが使っています。 | |
| # ============================================================ | |
| # | |
| # ぼくは動的プロクシをダックタイピングの代表だと思っています。 | |
| # 簡単に説明すると、動的プロクシというのは、要はすべてのメッセージを別のオブジェクトに転送する事によって、そのオブジェクトがあたかもそのオブジェクトであるかのように偽装するオブジェクトです。 | |
| # 転送の前後に、別の処理をはさむことで、もともともオブジェクトの動作をまったく変えずに、処理を変えたりできます。 | |
| class OriginObject | |
| def hello! | |
| "hello, this is #{self.class}" | |
| end | |
| end | |
| class DynamicProxy < BasicObject | |
| # BasicObjectはObjectを継承しない、非常に限られたメソッドしか持たない事を保証された、動的プロクシのためのオブジェクトです。 | |
| # 具体的には、Objectが | |
| # :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :initialize .. :__send__ など大量のメソッドを持つのに対し、 | |
| # BasicObject は | |
| # :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__ | |
| # しかメソッドを持ちません。 | |
| # | |
| # 動的プロクシは通常、できるだけ多くのメソッドを別オブジェクトに転送したいので、BasicObjectを継承します。 | |
| # | |
| # もし、これだけでなく、BasicObjectが持つメソッドですら別のオブジェクトに転送したいならば、 | |
| # 全メソッドを | |
| # private *instance_methods | |
| # などで隠す必要があります。 | |
| # ============================================================ | |
| def initialize entity | |
| @entity = entity | |
| end | |
| # method_missingは、存在しないメソッドまたはプライベートなメソッドが | |
| # 呼び出された場合に、そのメソッドの呼び出しに使用された名前、引数を | |
| # 代わりに渡され呼び出されるメソッドです。 | |
| def method_missing funcname, *args, &blk | |
| @entity.send(funcname, *args, &blk).tap do |result| | |
| $stdout.puts "logging to: #{funcname}(#{args.join ', '}) # => #{result}" | |
| end | |
| end | |
| end | |
| origin = OriginObject.new | |
| puts origin.hello! | |
| # hello, this is OriginObject | |
| proxy = DynamicProxy.new origin | |
| puts proxy.hello! | |
| # logging to: hello!() # => hello, this is OriginObject | |
| # hello, this is OriginObject |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment