Deletions are marked like this. | Additions are marked like this. |
Line 27: | Line 27: |
これはJavaなどの静的型付けの言語ではいたし方ないし、これがあるがゆえに実行速度が高いわけである。つまり、実行時に渡されたオブジェクトにそのようなメソッドがあるかどうかを調べなくて済むわけである(もちろんリフレクションを用いて調べる場合は別)。 | これはJavaなどの静的型付けの言語ではいたし方ないし、これがあるがゆえに実行速度が高いわけである。つまり、実行時に渡されたオブジェクトにそのようなメソッドがあるかどうかを調べなくて済むわけである。コンパイル時にメソッドの有無を判定済みだからである(もちろんリフレクションを用いて調べる場合は別)。 |
Line 29: | Line 29: |
これに対して、ruby等の動的な言語は実行時にメソッドの有無を調べる。それがゆえに遅いし、完全なテスト(テストカバレッジ100%)が必要になる。例えば、スペルミスして「hell」などという呼び出しを記述してしまえば、そのミスはその行が実際に呼び出されるまではわからない。 | これに対して、ruby等の動的な言語は実行時にメソッドの有無を調べる。それがゆえにどうしても実行速度は上がらないし、完全なテスト(テストカバレッジ100%)が必要になる。例えば、スペルミスして「hell」などという呼び出しを記述してしまえば、そのミスはその行が実際に呼び出されるまではわからない。 |
Line 32: | Line 32: |
さて、Javaで上述のようなことをしたいならば、どうしても以下のように書く必要がある。 {{{ interface IHello { public void hello(); } class Greeter implements IHello { public void hello() { System.out.println("hello, world"); } } class Executer { public void execute(IHello someObject) { someObject.hello(); // IHelloにはhelloというメソッドがある。OK! } } ... new Executer(new Greeter()).execute(); }}} |
構造的部分型(structural subtyping)
むつかしそうな名前だが、やりたいことはきわめて簡単。 そもそもプログラミングを簡単にしたいがための仕組みなのだから。
やりたいこと
例えば、Javaでは以下のようには記述できない。
class Greeter { public void hello() { System.out.println("hello, world"); } } class Executer { public void execute(Object someObject) { someObject.hello(); // Objectにそんなメソッドはない!コンパイルエラー } } ... new Executer(new Greeter()).execute();
つまり、Executer.executeメソッドは「任意の」オブジェクトを受け入れ、そのhelloメソッドを呼び出したいわけだが、コンパイラはコンパイル時にパラメータの型を調べて、それにhelloというメソッドがなければエラーにしてしまう。実行時にはhelloというメソッドの定義されたGreeterオブジェクトが渡されているにも関わらずである。
これはJavaなどの静的型付けの言語ではいたし方ないし、これがあるがゆえに実行速度が高いわけである。つまり、実行時に渡されたオブジェクトにそのようなメソッドがあるかどうかを調べなくて済むわけである。コンパイル時にメソッドの有無を判定済みだからである(もちろんリフレクションを用いて調べる場合は別)。
これに対して、ruby等の動的な言語は実行時にメソッドの有無を調べる。それがゆえにどうしても実行速度は上がらないし、完全なテスト(テストカバレッジ100%)が必要になる。例えば、スペルミスして「hell」などという呼び出しを記述してしまえば、そのミスはその行が実際に呼び出されるまではわからない。
※私見だが、これがゆえにスクリプト言語のプログラマは「スペルミスをしないように」長い名前を避ける傾向があるように思われる。しかし、短い簡単な名前ばかりつけていけば、大規模なプログラムでは同じ名前がそこかしこに存在することになり、リファクタリング時には非常な問題になる。「この名前とあの名前は同じだが、同じものを指しているのかわからない」という状況になりうる。静的に決定することができないのだ。スクリプト言語が大規模プログラム作成に向いていないのはこのような理由だ。
さて、Javaで上述のようなことをしたいならば、どうしても以下のように書く必要がある。
interface IHello { public void hello(); } class Greeter implements IHello { public void hello() { System.out.println("hello, world"); } } class Executer { public void execute(IHello someObject) { someObject.hello(); // IHelloにはhelloというメソッドがある。OK! } } ... new Executer(new Greeter()).execute();