11

インターフェイスを強制的に列挙型で実装できるかどうか知りたいです。

私は次のインターフェースを持っています:

public interface MobileApplication {
    String name();
}

名前の一意性を保証する必要があるため、これは列挙型で実装する必要があります。ライブラリを設計しているので、ライブラリのユーザーを信頼できず、一意の名前がないと、ライブラリはまったく機能しません。

セキュリティがなくても大丈夫ですが、それが可能かどうか疑問に思います。ありがとう

4

5 に答える 5

17

残念ながら、コンパイル時にこれを行うことはできません。やのようなメソッドを要求することで、これに関するヒントを与えることができます。また、実行時に確認することもできます。ordinal()name()

「私はライブラリのユーザーを信用できない」について: インターフェイス JavaDoc で要件を文書化する限り、それに従わない人は誰でも彼が支払ったものを手に入れます。

equals()これは、誰かが正しく実装しなかった場合とまったく同じですhashCode()。コンパイラはそれを強制しませんが、それを壊すと、それらに依存するクラスも壊れます。

あなたが得ることができる最も近いものは、おそらく次のようなものです:

public interface EnumInterface<E extends Enum<E>> {
}

実装は次のようになります。

public enum MyInterfaceImpl implements EnumInterface<MyInterfaceImpl> {
  FOO,
  BAR;
}

「悪意のある」開発者が次のようなクラスを構築する可能性があるため、これは単なるヒントです。

class NotAnEnum implements EnumInterface<MyInterfaceImpl> {
}

全体として、ライブラリを誤用する方法は常に存在します。ライブラリ作成者の目標は、ライブラリを誤って使用するよりも、ライブラリを正しく使用する方が簡単になるようにすることです。誤って使用できないようにする必要はありません。

于 2012-08-23T09:51:19.703 に答える
1

インターフェイスを強制的に列挙型で実装できるかどうか知りたいです。

いいえそうではありません。インターフェイスは任意のクラスで実装でき、ライブラリのユーザーに列挙型の使用を強制することはできません。

于 2012-08-23T09:51:29.213 に答える
1

インターフェイスを強制的に列挙型で実装できるかどうか知りたいです。

できたとしても何の役にも立たないから

一意の名前がないと、ライブラリはまったく機能しません。

enum A implements MobileApplication {
    ONE
}
enum B implements MobileApplication {
    ONE
}
enum C implements MobileApplication {
    ONE
}

3 つの列挙値があり、すべてにname()orが付いていONEます。

于 2012-08-23T11:17:48.690 に答える
1

そうではありません。これを明確にチェックする Java コンパイラ プラグインを提供する場合を除きます。ただし、その場合でも、ライブラリのユーザーはそのようなプラグインを喜んで使用する必要があります。

したがって、カスタム Java コンパイラ プラグインを使用するアプローチは、ライブラリ ユーザーがエラーを防ぐために何らかの静的支援ツールを使用したい場合にのみ意味があります。このリンクは、Java プラグイン オプションを選択する場合に役立ちます。

于 2012-08-23T09:49:47.170 に答える
1

これはすべてのアプリケーションのケースで機能するわけではありませんが、ジェネリックを使用するライブラリを定式化することは、将来ライブラリを作成してこの質問を検討する人々にとっての解決策になる可能性があります。

たとえば、アプリケーションの「設定」を一般的に管理するライブラリ クラス (SettingsManagerBase) を作成し、これらの設定をコードで取得/設定できる保証された一意のキーが必要でした。だから私は自分のインターフェースを定義しました(ここでは、追加の「セキュリティ」のために受け入れられた回答からのアイデアも取り入れましたが、これは私のアプローチでは厳密に言えば必要ではありません):

// Part of my settings library
public interface SettingBase<E extends Enum<E>> {
    Object defaultValue();  // <-- Whatever interface is needed
}

そして私の実装:

// Part of my application that uses the settings library
public enum Setting implements SettingBase<Setting> {
    THEME,
    SHOW_DIALOGS,
    ...;

    @Override
    public Object defaultValue() { ... }  // <-- Required interface implementation, probably based on constructor arguments (not shown)
}

ここで重要なのは、設定マネージャー ライブラリ クラスが、SettingBase を実装する列挙型を指定する必要があることを指定することです (これは現在、完全な保証です)。

// Part of my settings library
public abstract class SettingsManagerBase<E extends Enum<E> & SettingBase<E>> {
    public void foo(E setting) {
        Object d = setting.defaultValue();  // We can safely use all methods from our interface
        String n = setting.name();          // We can safely use all enumeration methods, without needing to specify them manually in our interface or anything
    }
}

設定マネージャーの実装は次のようになります。

// Part of my application that uses the settings library
public class SettingsManager extends SettingsManagerBase<Setting> {
    // If you need to override a function then E just turns into Setting
    public void foo(Setting setting) { ... }
}

ライブラリ クラス (SettingsManagerBase) のジェネリック Enum 'E' に対応するクラス インスタンスが必要な場合は、次のようにします。

// Add to SettingsManagerBase
protected Class<E> mEnumClass;
public SettingsManagerBase(Class<E> enumClass) {
    mEnumClass = enumClass;
    // Now you can do things like call Enum.valueOf(...)
}

// Add to SettingsManager
public SettingsManager() {
    super(Setting.class);
}

この答えは私のユースケースに固有のように思えますが、列挙によってインターフェイスを強制的に実装したい他の多くの状況でこのアイデアを実装することは難しくありません。

于 2020-11-28T12:22:27.523 に答える