2

私は次のクラスを持っています。

public class Super{

  public static void useSubClass(){
     //I want to access the sub class object here, how.
  }
}

public class Sub1 extends Super{

}

public class Sub2 extends Super{

}

スーパークラスの静的メソッドからサブクラス オブジェクトにアクセスしたい。Sub1.useSubClass()つまり、メソッドを呼び出すと、にアクセスでき、Sub1.class使用するとSub2.useSubClass()、にアクセスできますSub2.class

スーパークラスからサブクラス オブジェクトにアクセスする方法はありますか。

4

7 に答える 7

4

一般に、スーパークラスからどのクラスが継承されるかがわからないため (また、何も想定しないでください!)、スーパークラスからそれを行うことはできません (すべきではありません!)。

やりたいことに応じて、次のような代替手段があります。

  • テンプレート パターンを使用して、サブクラスが実装する必要がある「フィラー メソッド」を定義します。これらのフィラー メソッドは、スーパークラスのテンプレート メソッドによって呼び出されます。
  • サブクラスによってオーバーライドされるメソッドを定義します。
  • サブクラスによって実装されるインターフェイスを定義します。

更新: @JB Nizet が指摘したように、質問を読み間違えた可能性があります。

スーパークラスの静的メソッドからサブクラスにアクセスしたい場合は、次のことができます(オブザーバー パターンに非常に似ています)。

  • スーパークラスで静的リスナーリストを定義し、それを呼び出しますList observerList
  • スーパークラスのコンストラクターで、クラス インスタンス自体をその static に追加します。observerList
  • すべてのサブクラスについて、自分自身を登録する(およびデコンストラクターで登録解除する)super()ために、コンストラクターから呼び出すのはサブクラスの責任です。observerList
  • 次に、スーパークラスの静的useSubClass()メソッドで、そのサブクラス インスタンスのリストを反復処理し、関心のある特定のインスタンス (おそらく何らかの引数で指定) を見つけて、それを使用して何かを実行できます。
于 2012-12-09T17:09:01.773 に答える
4

静的メソッドは継承されず、呼び出しは の呼び出しSub2.useSubClass()と厳密に同等Super.useSubclass()です。

この情報は存在しないため、取得する方法はありません。コンパイラは の呼び出しを許可しますがSub2.useSubclass()、 に変換しSuper.useSubclass()ます。

于 2012-12-09T17:12:47.263 に答える
1
public static void useSubClass(Super sub) {
    if (sub instanceof Sub1) {
        // Do something
    } else if (sub instanceof Sub2) {
        // Do something else
    } else {
        // Something else is extending Super
    }
}

しかし、より良い質問はなぜですか?サブクラスのメソッドを単純にオーバーライドすることはできませんか?

于 2012-12-09T17:14:47.773 に答える
0

私は何かを理解しました。注意して実装すれば機能します。

/** SuperClass.java **/
public abstract class SuperClass {

    public static void printClass(){
    System.out.println(new ImplementingClassRetriever().getCallingClass());
    }

    static class ImplementingClassRetriever extends SecurityManager{
    public Class getCallingClass() {
        Class[] classes = getClassContext();
        for (Class clazz : classes) {
        if (SuperClass.class.isAssignableFrom(clazz) && clazz != null
            && !clazz.equals(SuperClass.class)) {
            return clazz;
        }
        }
        return null;
    }
    }
}


/** Main.java **/
public class Main{
    public static void main(String[] args) {
    Sub.printClass(); //this does not work
    Sub.testStaticCall(); //this works!! :)
    }
}


class Sub extends SuperClass{

    public static void testStaticCall(){
    Sub.printClass(); //calling the method in the super class
    }
}

これは単なるおもちゃの例です。スーパークラスには、呼び出し元のクラスを取得するためのメソッドを含む静的クラスが含まれています。

サブクラスには、クラス名を出力するためのスーパークラスのメソッドを呼び出す別の静的メソッドがあります。

Mainクラス/関数には、継承されローカルに実装されたメソッドへの2つの呼び出しが含まれていますSub。呼び出し元のコンテキスト(つまりMain)はのサブクラスではないため、最初の呼び出しはnullを出力します。ただし、呼び出し元のコンテキストがのサブクラスになり、呼び出し元のクラスを決定できるためSuper、のデリゲートメソッドは機能します。SubSuperClass

于 2012-12-09T20:07:44.903 に答える
0

スーパークラスはサブクラスのメソッドを知ることができないため、できません。スーパークラスとサブクラスの両方を参照する新しいクラスを作成し、この新しいクラス内に静的メソッドを実装することを検討する必要があります

于 2012-12-09T17:11:08.953 に答える
0

記録として、クラス メソッドを使用して Python でこれを行うことができます。

class super(object):
    @classmethod
    def usesubclass(cls):
        print cls

class sub1(super):
    pass

class sub2(super):
    pass

このコードを使用すると、sub1.usesubclass()またはを呼び出して、およびクラスsub2.usesubclass()の表現をそれぞれ出力できます。sub1sub2

>>> sub1.usesubclass()
<class '__main__.sub1'>
>>> sub2.usesubclass()
<class '__main__.sub2'>

残念ながら、Java はそのようなメカニズムをサポートしていません。例をコンパイルするSub1.useSubClass()と、コンパイラは をSub1基本的な名前空間として使用してuseSubClass()メソッドを検索しますSuperが、それに関する情報は実際にコードにコンパイルされません。結果のバイトコードでは、呼び出しは単に 1 つの直接呼び出しであり、それ以上のものではSuper.useSubClass()ありません。

私はあなたの苦境に同情しますが、Java はまさにそれです。あなたが来ることができる最も近いものは、次のコードだと思います:

public class Super {
    public static <T extends Super> void useSubClass(Class<T> sub) {
    }
}

そして、そのメソッドをSuper.useSubClass(Sub1.class)orとして明示的に呼び出しますSuper.useSubClass(Sub2.class)

于 2012-12-09T17:36:08.537 に答える
-2

ただし、スーパークラスへの参照を作成して、それを任意のサブクラスに向けることができます。これは、実行時に動的に行うこともできます。これは、 ランタイム ポリモーフィズムの 1 つの方法です。

于 2012-12-09T17:37:02.867 に答える