web-dev-qa-db-ja.com

汎用ORの代わりにAND <T extends Number | CharSequence>

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

擬似コードのためにコンパイルされません

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

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

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

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

本当にそうしたい場合は、受け入れたクラスを独自のカスタムクラス内にラップする必要があります。あなたの例の場合、おそらく次のようなものです。

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番目の方法を使用して同じことを達成することはできませんか?

18
Guillaume

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

public abstract class Doer<T> {

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

}

// calling method

new Doer<Number>(){}.do(new Integer(5));
1
Fil

元の質問の場合:

_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;
    }
}
_

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

イントロスペクションmayクラス名を書き換えるAndroidのProGuardコード圧縮のために中断し、YourClassの代わりに、クラス、つまりQがに格納されることに注意してください。データベースであり、より多くのクラスを持つ新しいバージョンのアプリで復元する場合、クラスQはそれとは異なります。詳細については、ProGuardWebサイトを参照してください。 Androidでイントロスペクションを使用する場合は、このことに注意する必要があることをお知らせしたいと思います。

0
Matthias Ronge