るびきちさん、
回答とサンプルコードありがとうございます。

MustImplement は良い感じですね !!

(ただ、interface 相当なので、クラスにしてしまうと1つしか interface を実
装できなくなるので、Base を module に換えてみました)


毎度、ありがとうございます。


rubikitch wrote:
> From: murayama <locutus / pg8.so-net.ne.jp>
> Subject: [ruby-list:42683] Re: Javaの interfaceのようなもの
> Date: Sun, 13 Aug 2006 12:25:22 +0900
> 
> るびきちです。
> 
>> ・「スーパークラス」で必要なメソッドを全部定義し、例外を投げるように記述する。
>> (それらのメソッドはサブクラスで適切にオーバーライドすることが前提。)
> 
> ちょいやってみました。
> module_evalは言語レベルでどうにかするのにとても便利…柔軟性万歳。
> 
> 使い方はスーパークラス側でextendします。
> 
> class NotImplemented < Exception; end
> module MustImplement
>   def must_implement(*methods)
>     methods.each do |meth|
>       module_eval %{
>         def #{meth}(*args)
>           raise NotImplemented, "Method `#{meth}' must be implemented in subclass."
>         end
>       }
>     end
>   end
> end
> 
> 
> require 'test/unit'
> class TestMustImplement < Test::Unit::TestCase
>   # sample usage
>   class Base
>     extend MustImplement
>     must_implement :foo, :bar
>   end
> 
>   class NotImplementedClass < Base
>   end
> 
>   class ImplementedClass < Base
>     def foo
>       "implemented"
>     end
>     def bar
>       "implemented"
>     end
>   end
>   # /sample usage
> 
>   def test_not_implemted_class
>     assert_raise(NotImplemented) { NotImplementedClass.new.foo }
>   end
> 
>   def test_base
>     assert_raise(NotImplemented) { Base.new.foo }
>   end
> 
>   def test_implemented_class
>     assert_equal("implemented", ImplementedClass.new.foo)
>     assert_equal("implemented", ImplementedClass.new.bar)
>   end
> end
> 
>> ・起動時に、そのクラスのサブクラス一覧を取得し(これの取得方法はアプリ依存?
>> それともリフレクションとかで可能?)、それらサブクラス全てについて上記に該当する
>> メソッドを全て呼び出し、例外が出ないことを確認させる。(コンパイルエラーに相当。)
> 
> これはユニットテストでカバーできるのではないでしょうか?
> --
> rubikitch
> http://www.rubyist.net/~rubikitch/
> 


-- 

♪  吉田 裕美 (Yuumi Yoshida)
♪    Blog      http://d.hatena.ne.jp/yuum3/
♪    HomePage  http://www.ey-office.com/