![](/img/trans.png)
[英]Why can't I call a method (public or static) from an Abstact class of type subclass when creating an instance of the subclass in another function?
[英]How can I get an instance of a subclass of abstract class from a static method of another class?
我有以下类结构:
DataStore类:
PStore
: public abstract class PStore ...
CStore1
和CStore2
CStore1.getInstance(Id)
和CStore2.getInstance(Id)
工人班:
public abstract class PWork...
CWork1
和CWork2
现在的情况:
类CWork1
实现了一个内部类,其中以下代码访问了Store:
protected class fListener implements ActionListener { public void actionPerformed(ActionEvent ae) { CStore1.getInstance(Id).someMethod(); # NOTE: someMethod() is implemented in CStore2 as well } }
我需要在CWork2
实现相同的fListener
类
作为一个优秀的小软件开发人员,我不是简单地将fListener
从CWork1
复制/粘贴到CWork2
类,然后在其代码CStore1
CStore2
更改为CStore2
,而是决定将其迁移到父类。
我试图做的:
在PStore
创建一个名为getStoreInstance(int Id)
的抽象方法: public abstract PStore getStoreInstance(int Id);
在CStore1
将该方法实现为public PStore getStoreInstance(int Id) { return CStore1.getInstance(Id); }
public PStore getStoreInstance(int Id) { return CStore1.getInstance(Id); }
到现在为止还挺好。 它编译了所有3个Store类。
将fListener代码从PWork
复制到CWork1
类
显然,编译器抱怨它对CStore1类及其方法getStoreInstance()
一无所知
现在,我决定简单地调用新创建的getStoreInstance()
:
旧代码: CStore1.getInstance(Id).someMethod();
新代码: PStore.getStoreInstance(Id).someMethod();
编译器投诉 :“无法从PStore类型中对静态方法getStoreInstance(Id)进行静态引用”。
Eclipse提出的唯一“修复”是使getStoreInstance()方法保持静态,但是THAT也不起作用:
当我向抽象类的方法声明添加一个static
修饰符时: public static abstract PStore getStoreInstance(int Id);
- 编译器抱怨“PStore类型中的抽象方法getStoreInstance只能设置一个公开或受保护的可见性修饰符”
当我试图使方法非抽象时: public static PStore getStoreInstance(int Id);
它抱怨说这个方法需要一个身体(非常合理)
当我试图添加一个身体时,它要求我返回PStore对象......但是!!!! 我的抽象类PStore没有构造函数,所以我无法返回PStore对象!
我正确地解决了这个问题吗?
如果没有,我该怎么办呢?
如果我是,那么我如何解决原始投诉 “无法对非静态方法进行静态引用”,因为抽象类不允许我将该方法设为静态?
它看起来对我来说,你有两个同构的层次结构(如果我使用的是正确的术语)并且相应的类之间存在关系:
PStore PWork
/ \ / \
/ \ / \
CStore1 CStore2 CWork1 CWork2
^ ^ ^ ^
| | | |
|---------+--------------| |
| |
|---------------------|
但我不认为有一种内置的方式来表达Java中的这种关系。 不知何故,你将不得不做一些使这些关系明确的事情。 也就是说, CWork1
中需要有一些引用CStore1
东西, CWork2
中引用CStore2
,或者某种与它们相关联的列表或地图。
可能有一种解决这种结构的设计模式,但我现在想不到它。 所以,在我的脑海中,这里有几个可能的解决方案(两者都不使用反射):
将您在PWork
定义的抽象getStoreInstance
方法替换为PStore
。 在CWork1
,使用调用CStore1.getInstance
的方法覆盖它,类似地在CWork2
覆盖它。 然后,常见的fListener
actionPerformed
代码将调用getStoreInstance(Id).someMethod()
,没有类名,这可以在当前的PWork
实例上运行。 您仍然会有一些“重复”代码(因为您必须在两个CWork
类中实现getStoreInstance
),但它会保持最小化。
设置地图。 这编译(Java 8),但我没有测试它:
class PWork { private static Map<Class<? extends PWork>,IntFunction<PStore>> storeMap; static { storeMap = new HashMap<>(); storeMap.put(CWork1.class, CStore1::getInstance); storeMap.put(CWork2.class, CStore2::getInstance); } protected PStore getStoreInstance(int Id) { return storeMap.get(getClass()).apply(Id); } protected class fListener implements ActionListener { public void actionPerformed(ActionEvent ae) { int Id = ???; // I'm assuming Id is computed from ae somehow?? getStoreInstance(Id).someMethod(); } } }
现在, getStoreInstance
在地图中查找,使用当前PWork
对象的类( CWork1
或CWork2
)作为键,以确定要调用的getInstance
静态方法。
是的,您可以在PStore上使用静态方法并且没有重复代码。
使您的工作人员具有通用性,保留类令牌引用并调用
public class Worker<T extends PStore> {
private final Class<T> c;
public Worker(Class<T> c) {
this.c = c;
}
public void actionPerformed(ActionEvent ae) {
PStore.getInstance(c, Id).someMethod();
}
// other methods
}
现在对于PStore中的静态方法,它不必是通用方法:worker不必知道返回的实际类型,它只是正确的类型。
public class PStore {
private static Map<Class<?>, List<PStore>> map = new HashMap<>();
protected PStore() {
List<PStore> list = map.get(getClass());
if (list == null) {
list = new ArrayList<>();
map.put(getClass(), list);
}
list.add(this);
}
public static PStore getInstance(Class<? extends PStore> c, int i) {
return map.get(c).get(i);
}
public abstract void someMethod();
}
这里的好处是N个实例的上限留给了PStore子类。 还要注意列表如何包含PStore实例,它们实际上是子类实例,但PStore和worker都不关心(只要它实际上是返回的所需子类,它将是)。
免责声明:我在手机上输入了这个,所以可能无法编译 - 如果有问题请告诉我,我会尝试修复它。
编译器是正确的,因为在静态上下文中引用实例方法不起作用。 在静态世界中,您正在处理类级别并处理整个类的属性。 如果您尝试调用实例方法,编译器如何知道您要执行实例方法的实例?
制作抽象方法不起作用,因为抽象方法必须在子类中实现。 但是,静态方法不能被覆盖 - 只能隐藏。 因此,如果在抽象方法上允许static
,并且您尝试执行AbstractClass.staticMethod()
,那么运行时将使用哪些实现?
你的代码有点难以理解,但这就是我的想法。 基于名称, getStoreInstance(int Id)
应该确实是一个静态方法,因为实例获取另一个实例没有多大意义; 这似乎更像是班级应该做的事情。 您可能想重新考虑如何构建代码...从代码名称来看,您似乎应该使用类级别的方法来跟踪类的实例,因此可能会执行类似的操作并实现getInstance()
和getStoreInstance()
作为静态方法将是一个开始?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.