我可以在Java中重载接口方法吗?

Tim*_*imo 2 java overloading java-8

我有一个数据描述界面:

public interface DataDescription {
     int getId();
}
Run Code Online (Sandbox Code Playgroud)

两个实现:

public class DataWithId1 implements DataDescription {
    // ... simple getter impl.
}

public class OtherDataWithId implements DataDescription {
    // ... simple getter impl.
}
Run Code Online (Sandbox Code Playgroud)

现在我有这个界面:

public interface DataProcessor {
    void process(DataDescription data);
}
Run Code Online (Sandbox Code Playgroud)

我想实现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)
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一些代码可以调用它:

public Main {
    private DataProcessor dataProcessor = new DataProcessor();

    public static void main(String[] args) {
        DataDescription data = new DataWithId1(1);
        dataProcessor.process(data);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是DataProcessor调用者不必担心数据转换(他们有一个DataDescription并且不必知道这两种类型).另外我想避免instanceof代码.

我做的假设是我可以重载这样的接口方法.在查看java语言规范的第15.12节时,我无法找到证据(这并不意味着它不存在......).

我对重载的假设是否正确?我可以避免instanceof吗?

Era*_*ran 5

不,这不行.

您的代码中没有重载.dataProcessor的静态类型是DataProcessor,DataProcessor只有一种process方法.

如果将dataProcessor静态类型更改为DataProcessorImpl,则仍然无法获得所需的结果,因为在编译时确定了重载分辨率.因此,由于编译时类型dataDataDescription,dataProcessor.process(data)仍然会调用public void process(DataDescription data)而不是public void process(DataWithId1 data).


Hol*_*ger 5

也许您正在寻找访客模式

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好吧,如果您在“DataProcessor”接口中声明所有“process”方法,则可以。但是,很容易将它们与前端“process”方法混淆。最干净的解决方案是有两个接口,一个由“accept”方法使用的“Visitor”接口,以及一个用于使用站点的“DataProcessor”接口(此处为“main”方法)。然后,“DataProcessorImpl”可以实现这两个接口。因此,“main”方法不必了解访问者接口,“accept”方法也不必了解“DataProcessor”(将来可能会有其他访问者)。 (2认同)