Java 如何从另一个类的静态方法中获取抽象类的子类的实例?
我的班级结构如下:Java 如何从另一个类的静态方法中获取抽象类的子类的实例?,java,static,abstract-class,subclass,instance-variables,Java,Static,Abstract Class,Subclass,Instance Variables,我的班级结构如下: 数据存储类: 父类:PStore:公共抽象类PStore… 扩展它的两个子类:CStore1和CStore2 每个子类都是一个N-glton(抱歉,不确定它的Java术语是什么)——它只能有N个实例,编号为1..NMax 每个子类都有以下访问该实例的方法:CStore1.getInstance(Id)和CStore2.getInstance(Id) 工人阶级: 父类:公共抽象类PWork… 扩展它的两个子类:CWork1和CWork2 当前情况: ClassCWo
- 数据存储类:
- 父类:
:PStore
公共抽象类PStore…
- 扩展它的两个子类:
和CStore1
CStore2
- 每个子类都是一个N-glton(抱歉,不确定它的Java术语是什么)——它只能有N个实例,编号为1..NMax李>
- 每个子类都有以下访问该实例的方法:
和CStore1.getInstance(Id)
CStore2.getInstance(Id)
- 父类:
- 工人阶级:
- 父类:
公共抽象类PWork…
- 扩展它的两个子类:
和CWork1
CWork2
- 父类:
- 当前情况:
- Class
实现了一个内部类,该类使用以下代码访问存储:CWork1
protected class fListener implements ActionListener { public void actionPerformed(ActionEvent ae) { CStore1.getInstance(Id).someMethod(); # NOTE: someMethod() is implemented in CStore2 as well } }
- 我需要在
CWork2
- 作为一名优秀的小软件开发人员,我没有简单地将
中的CWork1
复制/粘贴到fListener
类,然后在其代码中将CWork2
更改为CStore1
,而是像个傻瓜一样决定将其迁移到父类CStore2
- Class
- 我想做的是:
- 在
中创建名为PStore
的抽象方法:getStoreInstance(int-Id)
公共抽象PStore getStoreInstance(int-Id);
- 在
asCStore1
到目前为止,一切顺利。它编译了所有3个存储类publicpstoregetstoreinstance(int-Id){return CStore1.getInstance(Id);}
- 将fListener代码从
复制到PWork
类CWork1
- 显然,编译器抱怨它不知道任何关于CStore1类及其方法的信息
- 现在,我决定只调用新创建的
: 旧代码:getStoreInstance()
CStore1.getInstance(Id).someMethod()代码> 新代码:
PStore.getStoreInstance(Id).someMethod()代码>
- 在
- 编译器投诉:“无法从类型PStore对非静态方法getStoreInstance(Id)进行静态引用”
- Eclipse提出的唯一“修复”方法是将getStoreInstance()方法设为静态,但这也不起作用:
- 当我在抽象类的方法声明中添加了一个
修饰符时:static
publicstaticabstractpstore-getStoreInstance(int-Id)代码>-编译器抱怨“PStore类型中的抽象方法getStoreInstance只能设置可见性修饰符,公共修饰符或受保护修饰符之一”
- 当我试图使方法非抽象时:
publicstaticpstore getStoreInstance(intid)代码>它抱怨该方法需要一个主体(相当合理)
- 当我尝试添加实体时,它要求我返回PStore对象。。。但是我的抽象类PStore没有构造函数,所以我无法返回PStore对象
- 当我在抽象类的方法声明中添加了一个
我处理问题的方法正确吗? 如果没有,我应该如何处理它?
如果我是,那么我如何解决最初关于“无法对非静态方法进行静态引用”的抱怨,因为抽象类不允许我将该方法设置为静态方法?编译器是正确的,因为在静态上下文中引用实例方法不起作用。在静态世界中,您在类级别上工作,处理整个类的属性。如果尝试调用实例方法,编译器如何知道要执行实例方法的实例 制作抽象方法是行不通的,因为抽象方法必须在子类中实现。但是,静态方法不能被重写——只能被隐藏。因此,如果在抽象方法上允许使用
static
,并且您尝试执行AbstractClass.staticMethod()
,那么运行时将使用什么实现
你的代码有点难理解,但我是这么想的。仅根据名称,
getStoreInstance(intid)
实际上应该是一个静态方法,因为一个实例获取另一个实例没有多大意义;这似乎更像是全班应该做的事情。您可能需要重新思考如何构建代码。。。从代码名来看,您似乎应该有一种类级的方法来跟踪类的实例,因此,也许可以这样做,并将getInstance()
和getStoreInstance()
实现为静态方法,这将是一个开始?在我看来,您有两个同构的类层次结构(如果我使用了正确的术语)并且相应的类之间存在关系:
PStore PWork
/ \ / \
/ \ / \
CStore1 CStore2 CWork1 CWork2
^ ^ ^ ^
| | | |
|---------+--------------| |
| |
|---------------------|
但我认为Java中没有一种内置的方式来表达这种关系。
不知何故,您将不得不做一些事情来明确这些关系。例如,在CWork1
中需要有一些内容引用CStore1
,在CWork2
中需要有一些内容引用CStore2
,或者需要某种列表或映射来关联它们
可能有一种设计模式可以解决这种结构,但我现在想不起来。因此,在我的脑海中,有两种可能的解决方案(都不使用反射):
PWork
中定义的抽象getStoreInstance
方法替换为PStore
。在CWork1
中,使用调用CStore1.getInstance
的方法覆盖它
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();
}
}
}
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
}
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();
}