2009-07-30 11 views

答えて

8

Javaには、あなたが望む限り近いものはありませんが、代替案があります。デリゲートパターンは実装するのが難しくありませんが、Objective-Cで行うのと同じくらい便利ではありません。言語はあなたがそれらをサブクラス化、あるいはソースコードへのアクセスを持たずに、既存のクラスにメソッドを追加することができカテゴリを、サポートしているので、Objective-Cの中

理由「非公式プロトコル」作品です。したがって、ほとんどの非公式プロトコルはNSObjectのカテゴリです。これは明らかにJavaでは不可能です。

Objective-C 2.0はオプションのプロトコルメソッドを選択します。これははるかに洗練された抽象化であり、新しいコードには適していますが、Javaに同等の機能を持たせることができます。

正直言って、最も柔軟なアプローチは、デリゲートプロトコルを定義してから、クラスにすべてのメソッドを実装させることです。多くのJavaインターフェイスには付属のアダプタクラスがあります。これは、ユーザに空のメソッドをたくさん実装する必要がない一般的なアプローチですが、継承が制限されるため、コード設計が柔軟性がなくなります。 (ジョシュ・ブロッホは彼の著書「Effective Java」でこれを解説しています)。私の提案は、まずインターフェイスを提供し、本当に必要な場合はアダプタを追加することです。

"実行されていない"メソッドの場合はUnsupportedOperationExceptionを投げないようにしてください。これにより、委譲クラスは強制的にオプションのメソッドの例外を処理します。正しい方法は、何もしないメソッドを実装すること、デフォルト値を返すことなどです。これらの値は、void戻り値の型を持たないメソッドについては十分に文書化する必要があります。

2

Javaオブジェクトでデリゲートパターンを使用するのを止めることはありません(これはCocoaのようにJDKでは一般的に使用されているパターンではありません)。 WhateverDelegateインターフェイスに準拠した型のdelegateのivarを持っていて、委譲したいインスタンスメソッドでメソッド呼び出しがあればそれを委譲オブジェクトに転送してください。 Obj-Cの代わりにJavaを除いて、thisのように見えるもので終わるでしょう。

オプションのインターフェイスがあれば、それは難しくなります。私は、インターフェイスを宣言し、オプションのメソッドを空のメソッドとして実装する抽象クラスを宣言し、抽象クラスをサブクラス化し、この特定のオブジェクトで実装するオプションのメソッドをオーバーライドすることをお勧めします。 Javaでは多重継承が欠如しているため、潜在的に厳しい制限がありますが、これは私が思い付くほど近いものです。

+4

Throwing「UnsupportedOperationException」はひどい考えです! APIは、通常の使用パターンでユーザーに例外処理を強いるべきではありません。 Cocoaのデリゲートパターンは、実装されていないデリゲートメソッドを静かに渡すという点で堅牢です。 –

+0

非常に良い点。私は迷惑なJavaの例外がどのように忘れていた。 –

+0

@Quinn Taylor:しかし、これはJavaライブラリの多くの部分で "オプションの"プロトコル*がどのように*行われたかです。たとえば、「Collection」インタフェースは、add()やremove()などのメソッドが「オプションの操作」であり、サポートされていない場合はUnsupportedOperationExceptionをスローすることを指定します。 – newacct

5

私が考えることができる非公式のプロトコルと最もよく似たのは、実装者がすべてのメソッドを実装することを避けるためのアダプタクラスも持つインターフェイスです。

public class MyClass { 

    private MyClassDelegate delegate; 

    public MyClass() { 

    } 

    // do interesting stuff 

    void setDelegate(MyClassDelegate delegate) { 
     this.delegate = delegate; 
    } 

    interface MyClassDelegate { 
     void aboutToDoSomethingAwesome(); 
     void didSomethingAwesome(); 
    } 

    class MyClassDelegateAdapter implements MyClassDelegate { 

     @Override 
     public void aboutToDoSomethingAwesome() { 
      /* do nothing */ 
     } 

     @Override 
     public void didSomethingAwesome() { 
      /* do nothing */ 
     } 
    } 
} 

その後、誰かが一緒に来て、ちょうど彼らが気にものを実装することができます。

class AwesomeDelegate extends MyClassDelegateAdapter { 

    @Override 
    public void didSomethingAwesome() { 
     System.out.println("Yeah!"); 
    } 
} 

いずれかの方法で、「知られている」こと、あるいは純粋な反射呼び出し。しかし、それは気違いです。

+0

しかし、いつものように、アダプター・アプローチは人為的に継承を制限します。 JavaにはプロトコルでObj-Cのようなオプションのインタフェースメソッドがありませんので、まったく同じものを得ることはありません。最もクリーンな(しかしまだ迷惑な)アプローチは、空のメソッドを実装することです。 –

関連する問題