Observable で mixin の復習など

Ruby で言う Module はその中でメソドを定義することはできるけれど、オブジェクトを生成して定義されたメソドを呼び出す、などということはできない。ただし include という操作 (というか Module クラスのメソド呼び出し) によりそのクラスで include した module で定義されているメソドを呼び出すことができるようになる。
ええと例えば以下な module があるとして

module Bar
  def baz
  end
end

みたいな定義だとすると、ここで定義されている baz というメソドを Foo というクラスのオブジェクトから呼び出すことができるようにするには

class Foo
  include Bar
end

してあげれば可能とのこと。

Foo.new.baz

これを使う形でも interface のようなことは可能だけれど定義時点で実装を強制するような事は当り前ですが不可能ですね。

GoF の Observer パターン

これって Observable という module を include してあげれば良い模様。

Observable というのは

  • オブジェクトの状態が変わる可能性があり
  • 変わったことを他のオブジェクトに通知する必要がある

という場合に適用すれば幸せになれる模様。基本的な使用方法については以下とのこと。

Observableモジュールをincludeしたクラスは Observable#changedメソッドにより更新フラグを立て、 Observable#notify_observers()が呼び出されると 更新フラグが立っている場合はオブザーバに通知する (オブザーバのupdateメソッドを呼び出す)。 Observable#notify_observers()の引数は そのままオブザーバのupdateメソッドに渡される。

Observable より引用

ちなみに

Observable によれば Observable#add_observer は引数で渡されるオブジェクトが update メソドを持っていない場合、例外を、とのこと。おそらくは add_observer される時に、だろうとは思いましたが確認してみました。

irb(main):001:0> require 'observer'
=> true
irb(main):002:0> class AObservable
irb(main):003:1> include Observable
irb(main):004:1> end
=> AObservable
irb(main):005:0> obj = AObservable.new
=> #<AObservable:0x00000001207078>
irb(main):006:0> class Foo end
SyntaxError: (irb):6: syntax error, unexpected keyword_end, expecting '<' or ';' or '\n'
(irb):6: syntax error, unexpected $end
        from /home/rms/.rbenv/versions/1.9.3-p327/bin/irb:12:in `<main>'
irb(main):007:0> class Foo
irb(main):008:1> end
=> nil
irb(main):009:0> observer = Foo.new
=> #<Foo:0x000000011c6280>
irb(main):010:0> obj.add_observer(observer)
NoMethodError: observer does not respond to `update'
        from /home/rms/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/observer.rb:129:in `add_observer'
        from (irb):10
        from /home/rms/.rbenv/versions/1.9.3-p327/bin/irb:12:in `<main>'
irb(main):011:0> 

微妙ですが、add_observer した時点で update が実装されているかどうかを確認していますね。これってどうやっているのかな。ある意味 interface を強制云々な解とも言えますね。

追記

ありました。Object#respond_to? メソドというものがありました。

しかしこのケイスってのは受け取ったオブジェクトが update というメソドを実装しているかどうか、ということを強制するためのものであってやっぱ何らかの interface 的なナニではないですね。うーん。