From: Minero Aoki Date: 1999-02-12T17:51:40+09:00 Subject: [ruby-list:12047] Re: What's DelegateClass ? あおきです。 In Mail "[ruby-list:12017] Re: What's DelegateClass ?" じぶん wrote: > > |ですね,これは使いでがあるので何かドキュメントがあったほうが > > |よいかも. > > > > テクニカルライター募集中.^^;;; > 応募(?)してもいいでしょうか。 とりあえず書いてみました。 ------------------------------------------------------------------- あおきみねろう@一橋大学 mail to: aamine@dp.u-netsurf.ne.jp website: http://www1.u-netsurf.ne.jp/~brew/mine/ ====================================================================

Delegator

クラス階層とは関係なく、他のオブジェクトのインターフェイス・ 実装を利用する(以下、delegate)ための抽象クラスです。 Delegatorクラスはオブジェクト単位のdelegateを行うためのクラス なので、クラス単位でdelegateをするときには、DelegateClass メソッドを使ってください。 ちなみに、このクラスには下位互換性のためにDelegaterという別名 があります。

スーパークラス:

Object

クラスメソッド:

new([obj])

引数objにはdelegateしたいオブジェクトを渡します。 下位クラスでinitializeを再定義するときは必ず superを呼びだす必要があります。

また、メソッドhash、eql?はdelegateされないので、Delegator の下位クラスのインスタンスをHashのキーに使うときは、この ふたつのメソッドを再定義してください。具体的には、

obj.eql? Delegator.new( obj )
obj.hash == Delegator.new( obj ).hash
の両方が成立する必要があります。

メソッド:

__getobj__

下位クラスでは目的にあわせてこのメソッドを再定義しなければ いけません。このメソッドが再定義されないままだと、そのクラス のメソッドが呼ばれたときに例外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に出力される

SimpleDelegator

SimpleDeletatorクラスは、クラス作成時または__setobj__であたえた オブジェクトのdelegateを行うクラスです。

スーパークラス:

Delegator

クラスメソッド:

new([obj])

引数objにはその実装を利用したいオブジェクトを渡します。

メソッド:

__getobj__
__getobj__

このクラスでは単にインスタンス変数に格納されているオブジェクトを 渡すだけです。

__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

===================================================================