31

ClassA OR InterfaceB のいずれかを受け入れるメソッドを一般的にパラメータ化することは可能ですか?

| が原因でコンパイルされない 疑似コード

public <T extends Number | CharSequence> void orDoer(T someData){ // ... }

つまり、複数のメソッド シグネチャを記述する代わりに、この 1 つのメソッドで Number または CharSequence を引数として受け入れるようにしたいと考えています。

Number OR CharSequence 引数で渡す必要があります

orDoer(new Integer(6));
int somePrimitive = 4;
orDoer(somePrimitive);
orDoer("a string of chars");
4

3 に答える 3

20

本当にそれをしたいのなら、あなたはあなた自身のカスタムクラスの中にあなたの受け入れられたクラスを包む必要があるでしょう。あなたの例の場合、おそらく次のようなものです。

public class OrDoerElement {
    private final Number numberValue;
    private final CharSequence charSequenceValue;

    private OrDoerElement(Number number, CharSequence charSequence) {
        this.numberValue = number;
        this.charSequenceValue = charSequence;
    }

    public static OrDoerElement fromCharSequence(CharSequence value) {
        return new OrDoerElement(null, value);
    }

    public static OrDoerElement fromNumber(Number value) {
        return new OrDoerElement(value, null);
    }
}

そしてあなたのorDoer方法は次のようになります:

public void orDoer(OrDoerElement someData) { .... }

次に、それらの1つを作成し、次のいずれかを使用してメソッドで使用できます。

orDoer(OrDoerElement.fromCharSequence("a string of chars"));
orDoer(OrDoerElement.fromNumber(new Integer(6)));

しかし、正直なところ、これは少し複雑すぎて、さまざまなパラメータータイプでメソッドを呼び出すことができないほど多くの作業が必要になります。2つの方法と、共通論理の3番目の方法を使用して同じことを達成することはできませんか?

于 2011-11-30T17:49:26.863 に答える
1

匿名の抽象クラスを使用するオプションはありますか?タイプセーフなパラメーターまたはリターンタイプが必要な場合は、以下のコードのいくつかのバリアントを使用します。そうは言っても、私はここにある他のコメントに同意します。あまり共通点がないオブジェクトのグループに型安全性を適用するときに、実際にどのようなメリットが得られるのか興味があります。

public abstract class Doer<T> {

  public void do(T obj) {
    // do some stuff. 
  }

}

// calling method

new Doer<Number>(){}.do(new Integer(5));
于 2011-11-30T19:20:16.997 に答える
0

元の質問の場合:

public void orDoer(Object someData){
    assert someData instanceof Number || someData instanceof CharSequence;

    // ...
}

より具体的なケースでは、assertステートメントはイントロスペクションを使用して、オブジェクトが必要な詳細を持っているかどうかを明確にする必要があります。つまり、String からコンストラクターをチェックし、プローブしtoString()て着信オブジェクトの結果からオブジェクトの新しいインスタンスを作成し、比較します。両方が等しい場合:

public void orDoer(Object someData) {
    assert isUniconstructable(someData);
}

public static boolean isUniconstructable(Object object) {
    try {
        return object.equals(object.getClass().getConstructor(String.class)
            .newInstance(object.toString()));
    } catch (InstantiationException | IllegalAccessException | InvocationTargetException
            | NoSuchMethodException| RuntimeException e) {
        return false;
    }
}

(例外がスローされる可能性があるため、アサート テストを独自の関数にラップする必要があります。)

クラス名を書き換える Android の ProGuard コード圧縮が原因でイントロスペクションYourClass壊れる可能性があることに注意してください。つまり、単なるクラスではなくQ、データベースに保存されます。クラス、クラスQは別のものです。詳細については、ProGuard の Web サイトを参照してください。Android でイントロスペクションを使用する場合は、この点に注意してください。

于 2018-08-09T07:09:56.080 に答える