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");
本当にそうしたい場合は、受け入れたクラスを独自のカスタムクラス内にラップする必要があります。あなたの例の場合、おそらく次のようなものです。
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番目の方法を使用して同じことを達成することはできませんか?
匿名の抽象クラスを使用するオプションはありますか?型セーフなパラメーターまたは戻り値の型が必要な場合は、以下のコードの変形を使用します。そうは言っても、私はここにある他のコメントに同意します。あまり共通点がないオブジェクトのグループに型安全性を適用するときに、実際にどのようなメリットが得られるのか興味があります。
public abstract class Doer<T> {
public void do(T obj) {
// do some stuff.
}
}
// calling method
new Doer<Number>(){}.do(new Integer(5));
元の質問の場合:
_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でイントロスペクションを使用する場合は、このことに注意する必要があることをお知らせしたいと思います。