我能从Java中的超类中知道扩展类吗?

时间:2012-12-09 17:06:28

标签: java inheritance

我有以下课程。

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

有没有办法从超类访问子类对象。

7 个答案:

答案 0 :(得分:4)

一般情况下,你不能从超类中做到这一点(而且不应该!),因为你不会知道(并且不应该假设任何东西!)哪些类将从你的超类继承。

根据您想要做的事情,有其他选择,例如:

  • 使用template pattern定义子类必须实现的“填充方法”;这些填充方法将由您的超类中的模板方法调用。
  • 定义要被子类覆盖的方法。
  • 定义要由子类实现的接口。

更新:正如@JB Nizet指出的那样,我可能误解了这个问题。

如果您希望从超类中的静态方法访问子类,可以执行以下操作(非常类似于Observer Pattern):

  • 在超类中定义静态侦听器列表,将其命名为List observerList
  • 在超类的构造函数中,将类实例本身添加到该静态observerList
  • 对于所有子类,他们有责任从他们的构造函数中调用super(),以便将自己注册到observerList(并在解构器中取消注册)
  • 然后在您的超类的静态useSubClass()方法中,您可以遍历该子类实例列表,找到您关心的特定实例(可能由某个参数指定),然后对其执行某些操作。

答案 1 :(得分:4)

静态方法不是继承的,调用Sub2.useSubClass()完全等同于调用Super.useSubclass()

无法获取此信息,因为它不存在。编译器允许调用Sub2.useSubclass(),但将其转换为Super.useSubclass()

答案 2 :(得分: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
    }
}

然而,更好的问题是为什么?你不能简单地覆盖你的子类中的方法吗?

答案 3 :(得分:0)

不,你不能因为超类不能知道子类的方法。 您应该考虑创建一个新类,它既可以看到超类,也可以在这个新类中实现静态方法

答案 4 :(得分: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方法,但没有相关信息。实际上编译成代码。在生成的字节码中,调用只是直接调用Super.useSubClass()而不再是。

我同情你的困境,但Java就是这样。我认为,你最接近的是以下代码:

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

然后将该方法明确地称为Super.useSubClass(Sub1.class)Super.useSubClass(Sub2.class)

答案 5 :(得分: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的子类因此可以确定通话类。

答案 6 :(得分:-2)

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