From: Minero Aoki
クラス階層とは関係なく、他のオブジェクトのインターフェイス・
実装を利用する(以下、delegate)ための抽象クラスです。
Delegatorクラスはオブジェクト単位のdelegateを行うためのクラス
なので、クラス単位でdelegateをするときには、DelegateClass
メソッドを使ってください。
ちなみに、このクラスには下位互換性のためにDelegaterという別名
があります。
引数
また、メソッドhash、eql?はdelegateされないので、Delegator
の下位クラスのインスタンスをHashのキーに使うときは、この
ふたつのメソッドを再定義してください。具体的には、
Delegator
スーパークラス:
クラスメソッド:
new([obj])
objにはdelegateしたいオブジェクトを渡します。
下位クラスでinitializeを再定義するときは必ず
superを呼びだす必要があります。
の両方が成立する必要があります。
obj.eql? Delegator.new( obj )
obj.hash == Delegator.new( obj ).hash
下位クラスでは目的にあわせてこのメソッドを再定義しなければ いけません。このメソッドが再定義されないままだと、そのクラス のメソッドが呼ばれたときに例外NotImplementErrorが発生します。
#!/usr/local/bin/ruby
require 'delegate'
class SimpleDelegator < Delegator
# SimpleDelegatorの定義そのまま。
# 他に例が思いつかないところが苦しい
def __getobj__
@obj
end
def __setobj__( obj )
@obj = obj
end
def initialize( obj )
super
__setobj__( obj )
end
end
dele = SimpleDelegator.new( STDOUT )
dele.write 'this is from delegated STDOUT' # STDOUTに出力される
SimpleDeletatorクラスは、クラス作成時または__setobj__であたえた オブジェクトのdelegateを行うクラスです。
Delegator
new([obj])
引数objにはその実装を利用したいオブジェクトを渡します。
このクラスでは単にインスタンス変数に格納されているオブジェクトを 渡すだけです。
__setobj__(obj)
delegateを行うオブジェクトをobjに変更します。
#!/usr/local/bin/ruby require 'delegate' require 'socket' class SMTPsocket < SimpleDelegator def initialize( host = 'localhost', port = 25 ) # 組みこみクラスでインスタンス変数が使える。 # 現状で一番有効な利用法という話もある。 @sock = TCPsocket.open( host, port ) # 忘れてはいけない super( @sock ) end # 定義をいろいろ書く… end
DelegateClass(dele_class)
第一引数に与えられたクラスのクラスメソッド・メソッドを ほぼ全て持った名無しクラスを新しく作ってそれを返します。 またそのクラスでは、必ずinitializeでdele_classのインス タンスをsuperに渡さなければいけません。
#!/usr/local/bin/ruby
require 'delegate'
class NilArray < DelegateClass( Array )
def initialize
super( [] )
# Arrayは組みこみクラスなので今のところインスタンス
# 変数は使えないが、Delegateされたクラスなら
# インスタンス変数が使える
@a = 1
end
def []( idx )
# 常にnilをかえすように変更してみる
return nil
end
end
obj = NilArray.new( 3 )
p obj.type # Array
obj.push 1
p obj[ 0 ] # nil (ちゃんと変更されている)
p obj # [ 1 ]
p obj.pop # 1