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
  • 在超类的构造函数中,将类实例本身添加到该静态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

不,你不能,因为超类不知道子类的方法。您应该考虑创建一个同时看到超类和子类的新类,并在这个新类中实现静态方法

于 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()or sub2.usesubclass(),这将分别打印sub1sub2类的表示:

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

然而,不幸的是,Java 不支持这种机制。当您Sub1.useSubClass()在您的示例中编译时,编译器将简单地Sub1用作基本命名空间来查找 中的useSubClass()方法Super,但实际上并没有关于该方法的信息被编译成代码。在生成的字节码中,调用只是直接调用,仅此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 回答
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调用。Sub第一次调用打印 null,因为调用上下文(即 Main)不是 的子类。Super但是委托方法在Sub工作,因为调用上下文现在是子类,SuperClass因此可以确定调用类。

于 2012-12-09T20:07:44.903 回答
-2

虽然您可以创建对超类的引用并将其指向任何子类。这也可以在运行时动态完成。这是 运行时多态的一种方式。

于 2012-12-09T17:37:02.867 回答