我能从Java中的超类知道扩展类吗?
我有以下课程我能从Java中的超类知道扩展类吗?,java,inheritance,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{ } 我想从超类中的静态方法访问子类对象。i、 e.当我调用Sub1.useSubClass()时,该方
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{
}
我想从超类中的静态方法访问子类对象。i、 e.当我调用Sub1.useSubClass()
时,该方法可以访问Sub1.class
,当我使用Sub2.useSubClass()
时,我可以访问Sub2.class
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
}
}
是否有任何方法可以从超类访问子类对象。一般来说,您不能从超类(也不应该!)访问子类对象,因为您不知道(也不应该假设!)哪些类将从您的超类继承 根据您想要做的事情,有其他选择,例如:
- 使用定义子类必须实现的“填充方法”;这些填充方法将由超类中的模板方法调用
- 定义要由子类重写的方法
- 定义子类要实现的接口
更新:正如@JB Nizet所指出的,我可能误解了这个问题 如果希望从超类中的静态方法访问子类,可以执行以下操作(非常类似于):
- 在您的超类中定义一个静态侦听器列表,将其称为
list observerList
- 在超类的构造函数中,将类实例本身添加到该静态
observerList
- 对于所有子类,它们都有责任从构造函数中调用
,以便将自己注册到super()
(并在解构器中注销)observerList
- 然后在超类的static
方法中,您可以迭代子类实例列表,找到您关心的特定实例(可能由某个参数指定),然后对其进行处理useSublass()
您应该考虑创建一个新的类,该类既可以看到超级类,也可以看到子类,在这个新类中实现静态方法 不继承静态方法,调用<代码>子2 .UsSub类(<)>代码>严格等同于调用<代码> Suth.UsSub类(<)/代码> . 无法获取此信息,因为它不存在。编译器允许调用
Sub2.useSubclass()
,但将其转换为Super.useSubclass()
然而,一个更好的问题是为什么?您不能简单地重写子类中的方法吗?请注意,您可以在Python中使用类方法执行此操作:
class super(object):
@classmethod
def usesubclass(cls):
print cls
class sub1(super):
pass
class sub2(super):
pass
使用此代码,您可以调用sub1.usesubclass()
或sub2.usesubclass()
,这将分别打印sub1
和sub2
类的表示:
>>> sub1.usesubclass()
<class '__main__.sub1'>
>>> sub2.usesubclass()
<class '__main__.sub2'>
然后将该方法显式调用为
Super.useSubClass(Sub1.class)
或Super.useSubClass(Sub2.class)
,尽管可以创建对该超类的引用并将其指向任何子类。这也可以在运行时动态完成。这是运行时多态性的一种方式。我发现了一些问题。如果小心实施,它会起作用
/** 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
的子类,因此可以确定调用类。调用静态方法时根本没有实例。你的问题没有多大意义。超类不知道扩展它的类。为什么不调用Sub1.getClass()@谢谢。我也有同样的怀疑。我只是想在rails中实现一个类似于超级ActiveRecord的类。想一想,问是否有一些东西在反思或者我不知道的东西。我想你误解了这个问题。OP没有调用实例方法,而是静态方法。我看不出当代码调用Sub2.useSubclass()
时,您的更新如何允许识别Sub2.class,尤其是在从未构造过任何类的实例的情况下。如果必须将参数传递给该方法,则只需调用Sub2.useSubclass(Sub2.class)
,解决方法是只使用提供的参数。不需要所有这些破碎的访客资料。@JBNizet更新了我的答案,添加了一些关于使用观察者列表的内容,但仍然有点粗糙。它不仅粗糙,而且完全破碎,没有必要。请阅读我之前的评论。静态方法不会被重写。为什么该方法具有静态属性?为什么。这就是要求。该方法在类上被调用,因此它们需要是静态的。
/** 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
}
}