我正在编写一个程序,需要对抽象对象Assignment
的子类进行CRUD操作。我有工厂来做CRUD操作,但是我在覆盖这些方法时遇到了问题。
public abstract class Assignment {
protected Integer id = null;
protected String name = null;
public Assignment() {}
public Assignment(Assignment original) { // code here to clone }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
具体作业
public class DCONAssignment extends Assignment {
protected Integer amount = null;
protected String type = null;
public DCONAssignment() {}
public DCONAssignment(DCONAssignment original) { // code here to clone }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
抽象工厂
public abstract class AssignmentProcessor {
public abstract Assignment loadAssignment(Integer assignmentId);
// public abstract boolean saveAssignment(Assignment assignment); // option 1
// public abstract boolean saveAssignment(<? extends Assignment> assignment); // option 2 // This says "abstract methods do not specify a body"
// public <T extends Assignment> boolean saveAssignment(T assignment) { //option 3
public boolean saveAssignment(Assignment assignment) { //option 4
return false;
}
protected Assignment loadAssignment(Integer assignmentId, Class<? extends Assignment> clazz) {
Assignment assignment = null;
try {
assignment = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
BurstAssignment burstAssignment = null; // load assignmnet from db
assignment.setId(burstAssignment.getId());
return assignment;
}
}
和混凝土工厂
public class DCONAssignmentProcessor extends AssignmentProcessor {
@Override
public DCONAssignment loadAssignment(Integer assignmentId) {
DCONAssignment assignment = (DCONAssignment) loadAssignment(assignmentId, DCONAssignment.class);
return assignment;
}
@Override
public boolean saveAssignment(DCONAssignment assignment) { // eclipse says I need to override a method with options 1, 3 and 4
return false;
}
}
总之,抽象工厂处理一些繁重的工作来装载作业。具体工厂处理其Assignment类的特定实现的详细信息。问题是用具体参数覆盖抽象方法。所以问题是,我如何在抽象工厂中指定一个方法并用具体工厂中的具体参数覆盖它?
答案 0 :(得分:2)
我解决了问题,解决方案是使抽象工厂通用
public abstract class AssignmentProcessor<T extends Assignment> {
public abstract T loadAssignment(Integer assignmentId);
public boolean saveAssignment(T assignment) {
return false;
}
protected Assignment loadAssignment(Integer assignmentId, Class<T> clazz) {
Assignment assignment = null;
try {
assignment = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BurstAssignment burstAssignment = SessionHelper.getSession().getBurstAssignment(assignmentId);
assignment.setId(burstAssignment.getId());
return assignment;
}
}
混凝土工厂
public class DarfAssignmentProcessor extends AssignmentProcessor<DarfAssignment> {
@Override
public DarfAssignment loadAssignment(Integer assignmentId) {
DarfAssignment assignment = (DarfAssignment) loadAssignment(assignmentId, DarfAssignment.class);
return assignment;
}
@Override
public boolean saveAssignment(DarfAssignment assignment) {
return false;
}
}
答案 1 :(得分:0)
JSYK:您不必覆盖getId
中的setId
,getName
,setName
和DCONAssignment
方法。它们从基类继承而来,你实际上并没有改变它们。
当您使用@Override
时,您告诉编译器您打算您正在创建的方法,以使用新方法替换父类中的方法。这意味着您期望父类具有相同名称和签名的方法。如果编译器看起来并且无法找到具有相同名称和签名的方法,则会生成错误。 Eclipse会接收错误,检查您的代码,并为您提供有关如何解决问题的建议。
选项1:public abstract boolean saveAssignment(Assignment assignment);
基类定义了一个带有Assignment
参数的方法。 DCONAssignment
是一个Assignment
,因此您只需在派生类中定义saveAssignment
方法即可接受Assignment
,并传入DCONAssignment
对象
要正常运行,您必须使用派生方法进行投射:
@Override
public boolean saveAssignment(Assignment assignment) {
if (assignment instanceof DCONAssignment)) {
DCONAssignment da = (DCONAssignment) assignment;
// ... save da
return true;
} else {
throw new IllegalArgumentException("Expected DCONAssignment");
}
}
选项2:public abstract boolean saveAssignment(<? extends Assignment> assignment);
在这里,您的基类方法明确声明它将接受任何扩展Assignment
的类。您可以在派生类中覆盖它,并再次检查实际的类以验证它是否被赋予了正确的类。
@Override
public boolean saveAssignment(<? extends Assignment> assignment) {
if (assignment instanceof DCONAssignment) {
DCONAssignment da = (DCONAssignment) assignment;
// ... save da
return true;
} else {
throw new IllegalArgumentException("Expected DCONAssignment");
}
}
选项3:public <T extends Assignment> boolean saveAssignment(T assignment)
同样,这与选项2相同,但明确地为模板类型指定了名称T
。
选项4:看起来与选项1相同,除了方法是否在基类中声明为抽象(无方法体)。
最简单的解决方法是使用选项1方法,使用instanceof
检查参数是否实际上是预期的类型,并进行强制转换。
更结构化的方法是将工厂类声明为基于模板。
public abstract class AssignmentProcessor<T extends Assignment> {
public abstract T loadAssignment(Integer assignmentId);
public abstract boolean saveAssignment(T assignment);
}
然后,您可以使用预期类型声明派生的处理器:
public class DCONAssignmentProcessor extends AssignmentProcessor<DCONAssignment> {
@Override
public DCONAssignment loadAssignment(Integer assignmentId) {
// Your load code
}
@Override
public boolean saveAssignment(DCONAssignment assignment) {
// Your save code
}
}
抽象工厂可以像以前一样实施任何常用方法来进行繁重的工作。