4

基本的に私が欲しいのは、必要な作業を行うために同じメソッドを呼び出すために、戻り値がわずかに異なる2つのパブリックメソッドです。どちらもプライベートメソッドの戻り値を返しますが、プライベートメソッドは、それを呼び出したパブリックメソッドに応じて正しい値を返す方法を知っています。

メソッドの例:

public Map<Type1, Type3> doSomething1();
public Map<Type2, Type3> doSomething2();

private Map<Type1/Type2, Type3> doSomething(); 

したがって、上記の例では、doSomething()は、どのパブリックメソッドが呼び出したかに応じて、MapのキータイプとしてType1またはType2のいずれかを返します。簡単なチェックを実行し、正しいタイプのオブジェクトをマップに入力することができます。

たぶん、これはいくつかの巧妙なJavaリフレクションを通じて行うことができますか?わからない。それはすべてかなり危険なように見えるので、これについてもっと良い方法があれば、私はすべての耳です。

4

7 に答える 7

8

ここでは、リフレクション モジョを避けることを強くお勧めします。関数は 1 つのことを適切に実行する必要があり、呼び出し元に依存してはなりません。

同じことを行うためのより良い方法は、doSomething() をより小さな関数にリファクタリングし、doSomethingFor1() と doSomethingFor2() という 2 つの新しい関数を作成することです。これらの関数は両方とも、古い doSomething() のリファクタリングされた部分を再利用できます。

doSomething1() を呼び出して doSomethingFor1() を使用します。

同様に、doSomething2() は doSomethingFor2() を使用する必要があります。

乾杯、

ジュニア。

于 2009-05-28T05:51:59.313 に答える
3

注意: 私は質問を誤解したので、この答えは質問が求めているものとは反対です。これはコミュニティウィキとして参照できるように残しておきますが、これは元の質問に答えるものではありません。

に共通のサブタイプがType1あり、とType2呼ばれるSuperType場合、最初のタイプがであると言うことは? extends SuperType機能します。

Integerこれは、とDoubleを2つのタイプとして使用し、それらの共通の祖先をNumber次のように使用する小さな例です。

private Map<Integer, String> doSomethingForInteger() {
  HashMap<Integer, String> map = new HashMap<Integer, String>();
  map.put(10, "Hello");
  return map;
}

private Map<Double, String> doSomethingForDouble() {
  HashMap<Double, String> map = new HashMap<Double, String>();
  map.put(3.14, "Apple");
  return map;
}

public Map<? extends Number, String> doSomething(boolean b) {
  if (b)
    return doSomethingForInteger();
  else
    return doSomethingForDouble();
}

ここで、メソッドは、渡されたに応じてdoSomething2つのタイプのsを返します。またはメソッドによって返されます。HashMapbooleanHashMap<Integer, String>HashMap<Double, String>doSomething

実際にaを呼び出すdoSomethingと、次のbooleanように実行できます。

Map<? extends Number, String> map1 = doSomething(true);
Map<? extends Number, String> map2 = doSomething(false);

map1で終わりますがHashmap<Integer, String>、をmap2取得しHashmap<Double, String>ます。

于 2009-05-28T06:15:53.097 に答える
1

任意のタイプパラメータから直接インスタンス化することはできないため、たとえば、タイプ1とタイプ2がどのようにインスタンス化されるかなど、質問から欠落している情報が少し必要です。ここで、type1とtype2の両方をインスタンス化するために使用されるいくつかの一般的なデータがあると想定します。そうでなければ、両方に1つの方法を使用する正当な理由はありません。後者の場合、これは1つの関数が型に基づいて2つの別々のことを行うことを意味しますが、これは悪いプログラミングです。呼び出し元のメソッドに直接基づくロジックを使用する場合は、2つのプライベートメソッドを用意して、一般的なものをリファクタリングします。

一部のデータに基づいて、インスタンス化のみを異なる方法で行う場合、これを行う最も簡単な方法は、プライベート内部インターフェイスを宣言することです。

private interface Instantiator<T> {

     T getNew(Data data);        

}

ここで、タイプをインスタンス化できると仮定すると、実際にこれを使用できます。

private <T> Map<T,Type3> doSomething(Instantiator<T> instantiator) {...}

メソッドシグネチャとして、適切なInstantiator実装を使用してパブリックメソッドに呼び出させます。

于 2009-05-28T06:13:20.713 に答える
1

他のすべてが失敗した場合は、プライベート メソッドがオブジェクトを返して、パブリック メソッドでキャストを使用できるようにします。

于 2009-05-28T05:49:20.097 に答える
1

最初の質問は、なぜこの正確な構造が必要なのかということです。

しかし、安全な方法はそれを元に戻すことです

public Map<Object, Type3> doSomething();

Type1 と Type2 に共通のスーパータイプがない場合。共通のスーパー タイプがある場合は、オブジェクトの代わりにそれを使用できます。

これが不要になるようにコードをリファクタリングすることをお勧めします。

于 2009-05-28T05:53:50.450 に答える
0

Closure のアイデアをモデル化できます:

interface MappingClosure {
    public void map(Map, MapProvider);
}


class Caller implements MappingClosure {
     public void map(final Map MAP, final MapProvider CALLEE) {
         this.MAP = specialise(MAP);
         // CALLEE USED AS KEY
     }
}


class MapProvider {  
    public Map getMap(final MappingClosure CALLER) {
        return CALLER.map(mapInstance, this);
    }
}

次に、オブジェクトのニーズに合わせてデータを変更することは、それを必要とするオブジェクト内のメソッドとは異なります。

于 2009-05-28T06:33:24.753 に答える
0

リフレクションを使用してスタックを分析することで、間違いなくそれを行うことができます。しかし、私はそれを避けようとします:

  • 基本型(またはオブジェクト)を返し、呼び出し元で適切にキャストします。とにかくこれを行う必要があります
  • なんらかの方法で何をすべきかを示すパラメーターをプライベート メソッドに渡し、戻ります
于 2009-05-28T05:52:40.823 に答える