3

getInstance()すべてのサブクラスに呼び出される静的メソッドを転送したいスーパークラスがあります。

サブクラスのインスタンスを作成するときは、そのインスタンスをスーパークラスに登録します (キーが に基づくハッシュテーブルを使用する可能性がありますgetClass())。getInstance次に、スーパークラス メソッドが正しい型のインスタンスを返す前述の静的メソッド ( ) を使用したいと思います。

たとえば、スーパークラス A があり、サブクラス B が A を拡張します。静的メソッドを書きたいとしますA.getInstance()。B ( B.getInstance()) から呼び出されたときに、以前に保存した B のインスタンスを返すようにしたいと考えています。

説明するのはちょっと難しいですが、私はこのスーパークラスをたくさん使うつもりですgetInstance

どうすればこのようなことをすることができますか?

編集:私の質問がオブジェクトの新しいインスタンスを作成すると誤解される可能性があることに気付きました. すでにインスタンスを作成しており、クラスの既存のインスタンスを取得したい

4

6 に答える 6

3

コメントで他の多くの人が指摘しているように、あなたがしようとしていることは静的メソッドでは不可能です。また、静的メソッドはテストとメンテナンスの悪夢につながる可能性があるため、できる限り避けるようにしてください (*)。

メソッドに「getInstance」という名前を付けたので、やりたいことは、Factory パターンと Singleton パターンの組み合わせだと思いますこれらのパターンを開始するための情報を次に示します。

シングルトン: http://en.wikipedia.org/wiki/Singleton_pattern
ファクトリ メソッド: http://en.wikipedia.org/wiki/Factory_method_pattern
抽象ファクトリ: http://en.wikipedia.org/wiki/Abstract_factory

最近では、どちらも手動でコーディングするべきではありません (*) - Google Guice や Spring などの優れた "依存性注入" (DI) コンテナーを調べてください。正確に何を達成したいのかは 100% わかりませんが、DI コンテナーがそれを実行してくれるようです。

編集:これは、質問の編集に対する応答です。サブクラスのキャッシュされたインスタンスを受け取りたい。この場合でも、静的メソッドは使用しないことをお勧めします。「BCache」クラスのシングルトン インスタンスを作成し (DI コンテナーを使用するか、手動でプログラミングします)、このキャッシュ オブジェクトを使用して登録済みオブジェクトを検索できます。Guice を DI コンテナーとして使用すると、次のようになります (警告、未テスト)。

@Singleton
public class BCache {
    private Map<Class<? extends B>, B> cache = ...;

    public <T> T getInstance(Class<? extends T> type) {
        return (T) cache.get(type);
    }
}

ただし、DIコンテナを使用してキャッシュクラスを完全に取り除くことはまだ可能だと思います。繰り返しますが、これは Guice を使用したテストされていないコードですが、次のようになります。

@Singleton
public class A extends B {
    public A() {
        //I am not sure if you need to register in this case, because your
        //DI container keeps track of the singleton instances.
        super.register(this);
    }
}

public class SomeClassUsingA {
    @Inject private A a;
}

(*) 「すべての一般化は間違っている」ことに注意してください。つまり、一部のプロジェクトでは意味があるかもしれませんが、ほとんどの場合はそうではありません。

于 2013-01-16T08:06:01.270 に答える
1

サブクラスのインスタンスをスーパークラスの参照にいつでも割り当てることができます。したがって、スーパークラスの静的メソッドは、サブクラス インスタンスを設定または取得できます。ただし、使用する前に、返されたインスタンスを必ずキャストしてください。

public class A {
    private static A a;

    /**
     * @param a the a to set
     */
    public static void setA(A a) {
        A.a = a;
    }

    /**
     * @return the a
     */
    public static A getA() {
        return a;
    }


public class B extends A {
    private int index = 0;

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }

使用法:

public static void main(String[] args) throws Exception {
        B b = new B();
        A.setA(b);

    B c = (B) A.getA();
    System.out.println(c.getIndex());
}
于 2013-01-16T08:18:48.007 に答える
1

良い OOP の方法では、静的メソッドを使用して、必要なことを正確に行うことはできません。のリフレクションまたは束で何かを行うことができますif .. else if

ただし、 Abstract fectoryFactory methodなどの明確に定義された設計パターンを使用する必要があります。誰かが「温水を発明するな」と言ったように、これがあなたが行くべき道です。

于 2013-01-16T08:11:07.840 に答える
0

スーパークラスでフォームgetInstance()を次のように変更します。getInstance(String class)

public static A getInstance(String class){
if(class.equals("A")){
RegisterObject(...);//User defined method
return new A(...);
}
else if(class.equals("B")){
RegisterObject(...);//User defined method
return  new B(...);
}
else if(class.equals("C")){
RegisterObject(...);//User defined method
return  new C(...);
}
//... and so on

}
于 2013-01-16T08:04:58.847 に答える
0

静的メソッドは、呼び出しに使用されたクラスを認識できません。たとえば、A を拡張してstatic getInstance()実装するクラス A と B がある場合、またはを使用しAて呼び出しても違いはありません。さらに、呼び出しを試みると、コンパイル警告が生成されます (少なくとも Eclipse では)。getInstance()ABB.getIntance()

ただし、クラスをのパラメーターとして渡すことができますgetInstance()

public class A {
    public static <T extends A> T getInstance(Class<T> clazz) {
        return clazz.newInstance(); // I do not catch exceptions here: do it yourself
    }
}

public class B extends A {
}

...............
B b = A.getInstance(B.class);
于 2013-01-16T08:08:16.480 に答える
0

あなたはこのようにすることができます、

 class A{
     public static A getInstance(){
     return new A();
   }

  @Override
  public String toString() {
   return "inside A";
   }
 }

 class B extends A{
public static A getInstance(){
  return new B();
 }

   @Override
   public String toString() {
      return "inside B";
   }
 }

内部メイン:

   public static void main(String[] args) {
  A a1 = A.getInstance();
  A a2 = B.getInstance();
      System.out.println(a1.toString());
  System.out.println(a2.toString());
   }
于 2013-01-16T08:13:34.633 に答える