我有一个数据描述界面:
public interface DataDescription {
int getId();
}
两个实现:
public class DataWithId1 implements DataDescription {
// ... simple getter impl.
}
public class OtherDataWithId implements DataDescription {
// ... simple getter impl.
}
现在我有了这个界面:
public interface DataProcessor {
void process(DataDescription data);
}
我想用一个类来实现DataProcessor
,类似这样:
public class DataProcessorImpl implements DataProcessor {
@Override
public void process(DataDescription data) {
// Do something...
}
public void process(DataWithId1 data) {
// Do something specific with this type (e.g. directly store in table of database)
}
public void process(OtherDataWithId data) {
// Do something specific with this type (convert to format DataWithId1 and then store in DB)
}
}
还有一些代码可以调用它:
public Main {
private DataProcessor dataProcessor = new DataProcessor();
public static void main(String[] args) {
DataDescription data = new DataWithId1(1);
dataProcessor.process(data);
}
}
我想要实现的是DataProcessor
调用者不必担心数据转换(他们有DataDescription
并且不必知道这两种类型)。另外,我想避免使用instanceof
代码。
我做的假设是我可以重载这样的接口方法。在查看section 15.12 of the java language specification时我无法找到证据(这并不意味着它不存在......)。
我对重载的假设是否正确?我可以避免instanceof
吗?
答案 0 :(得分:5)
不,这不起作用。
您的代码中没有重载。 dataProcessor
的静态类型为DataProcessor
,而DataProcessor
只有一种process
方法。
如果将dataProcessor
的静态类型更改为DataProcessorImpl
,则仍然无法获得所需的结果,因为在编译时确定了重载分辨率。因此,由于编译时类型data
为DataDescription
,dataProcessor.process(data)
仍会调用public void process(DataDescription data)
而不是public void process(DataWithId1 data)
。
答案 1 :(得分:4)
也许您正在寻找Visitor Pattern:
public interface DataDescription {
int getId();
void accept(DataProcessorImpl p);
}
public class DataWithId1 implements DataDescription {
private final int id;
public DataWithId1(int id) {
this.id=id;
}
@Override
public void accept(DataProcessorImpl p) {
p.process(this);
}
@Override
public int getId() {
return id;
}
// ... simple getter impl.
}
public class OtherDataWithId implements DataDescription {
private final int id;
public OtherDataWithId(int id) {
this.id=id;
}
@Override
public void accept(DataProcessorImpl p) {
p.process(this);
}
@Override
public int getId() {
return 42;
}
// ... simple getter impl.
}
public interface DataProcessor {
void process(DataDescription data);
}
public class DataProcessorImpl implements DataProcessor {
@Override
public void process(DataDescription data) {
data.accept(this);
}
public void process(DataWithId1 data) {
System.out.println("process(DataWithId1)");
// Do something specific with this type
// (e.g. directly store in table of database)
}
public void process(OtherDataWithId data) {
System.out.println("process(OtherDataWithId)");
// Do something specific with this type
// (convert to format DataWithId1 and then store in DB)
}
}
public class Main {
private static DataProcessor dataProcessor=new DataProcessorImpl();
public static void main(String[] args) {
DataDescription data = new DataWithId1(1);
dataProcessor.process(data);
data = new OtherDataWithId(100);
dataProcessor.process(data);
}
}
答案 2 :(得分:1)
如果在DataDescription
界面中的方法中添加“特定内容”,则很容易。
process()方法属于每个子类型。你把它放在了错误的界面上。
让DataProcessor
在每个DataProcessor
上调用该方法:
public interface DataDescription {
void somethingSpecific();
}
多态性完成工作:
public class DataProcessorImpl implements DataProcessor {
@Override
public void process(DataDescription data) {
data.somethingSpecific(); // polymorphism does it for you here
}
}
答案 3 :(得分:0)
您可以使用抽象类来处理转换,或者在接口中使用Java8的默认方法。
只需在界面中为方法添加关键字“default”,并为其指定正文。