JavaのCocoaデリゲート/ Objective-C非公式プロトコル?
-
06-07-2019 - |
質問
CocoaデリゲートのJava版は何ですか?
(インターフェイスをクラスに渡すことができ、そのクラスに適切なメソッドを呼び出すことができることを理解していますが、Cocoa / Objective-Cの非公式プロトコルに近いものを達成する他の方法があるかどうか疑問に思っています)
解決
簡単な答えは、Javaにはあなたが望むほど近いものはありませんが、代替手段はあります。デリゲートパターンを実装するのは難しくありません。Objective-Cで行うほど便利ではありません。
理由は「非公式プロトコル」 Objective-Cで動作するのは、言語がカテゴリをサポートしているためです。これにより、サブクラス化することなく、またはソースコードにアクセスすることなく、既存のクラスにメソッドを追加できます。したがって、ほとんどの非公式プロトコルはNSObjectのカテゴリです。これはJavaでは明らかに不可能です。
Objective-C 2.0は@optionalプロトコルメソッドを選択します。これは、よりクリーンな抽象化であり、新しいコードに適していますが、Javaに同等のものがあることからはさらに遠いです。
正直なところ、最も柔軟なアプローチはデリゲートプロトコルを定義し、クラスにすべてのメソッドを実装させることです。 (Eclipseのような現代のIDEでは、これは簡単です。)多くのJavaインターフェースには付随するアダプタークラスがあり、これはユーザーが多くの空のメソッドを実装することを要求しない一般的なアプローチですが、継承を制限し、コード設計を柔軟性のないものにします。 (Josh Blochは彼の著書「Effective Java」でこれに取り組んでいます。)私の提案は、最初にインターフェースを提供するだけで、本当に必要な場合はアダプターを追加することです。
何をするにしても、「未実装」に対して UnsupportedOperationException
をスローしないでください。メソッド。これにより、委任クラスはオプションのメソッドの例外を処理するようになります。正しいアプローチは、何もしない、デフォルト値を返すなどのメソッドを実装することです。これらの値は、void戻り値型を持たないメソッドについて十分に文書化する必要があります。
他のヒント
私が考えることができる非公式プロトコルに最もよく似ているのは、実装者がすべてのメソッドの実装を回避できるようにするアダプタークラスも備えたインターフェースです。
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!");
}
}
どちらか、または「既知」を呼び出す純粋なリフレクションメソッド。しかし、それは非常識です。
Javaオブジェクトでデリゲートパターンを使用するのを妨げるものは何もありません(CocoaのようにJDKで一般的に使用されるパターンではありません)。 WhateverDelegate
インターフェースに適合するタイプの delegate
ivarを用意し、デリゲートするインスタンスメソッドで、デリゲートオブジェクトが存在する場合はメソッド呼び出しを転送します。おそらく、 this のようなものになりますが、 Obj-Cの代わりのJava。
オプションのインターフェースに関する限り、それはより困難です。インターフェイスを宣言し、オプションメソッドを空のメソッドとして実装する抽象クラスを宣言し、抽象クラスをサブクラス化して、この特定のオブジェクトに実装するオプションメソッドをオーバーライドすることをお勧めします。 Javaには多重継承がないため、潜在的に深刻な制限がありますが、それは私が思いつく限り近くなっています。