如何摆脱类型转换?

How to get rid of typecasting?

我有一个胖接口:

public interface ISolver {
    void solve();   
    String printMsgs();    
    boolean hasSolution();    
    int getLeaderId();      
    void add(Agent agent);    
    void add(int item);    
    void add(String item);    
    void addAll(Agent[] data);    
    void addAll(int[] data);    
    void addAll(String[] data);     
    public void initiateStartState();       
    Agent next();    
    boolean hasNext();      
    public List<Integer> getLeftSenders();    
    public List<Integer> getRightSenders();    
    public List<Integer> getCurrentLeaders();    
    Agent get(int idx);    
}

有两个class继承了这个接口:

public class OneDirectSolver extends Solver{
    // some code..
}

public class BiDirectSolver extends Solver{
    // some code..
}

Class BiDirectSolver 使用了 ISolver 中声明的所有方法,但 OneDirectSolver 只使用了少数方法。我想遵循接口隔离原则。所以,我在 ISolver 中只留下了常用的方法。特定于 BiDirectSolver 的方法我移动到另一个扩展 ISolver

的接口
public interface ISolver {
    void solve();
    String printMsgs();
    boolean hasSolution();
    int getLeaderId();
    void add(Agent agent);
    void add(int item);
    void add(String item);
    void addAll(Agent[] data);
    void addAll(int[] data);
    void addAll(String[] data);
    public void initiateStartState();
    Agent next();
    boolean hasNext();
}

public interface BiDirectSolvable extends ISolver {
    public List<Integer> getLeftSenders();
    public List<Integer> getRightSenders();
    public List<Integer> getCurrentLeaders();
    Agent get(int idx);
}

但是现在我遇到了另一个问题。我试着描述一下。所以,我有 2 个 BiDirectSolverOneDirectSolver:

的客户
public class OneDirectPanel extends MyAbstractPanel {

    private OneDirectSolvable solver;

    public void setSolver(OneDirectSolver solver) {
        this.solver = solver;
    }
    //some code..
}

public class BiDirectPanel extends MyAbstractPanel {

    private BiDirectSolvable solver;

    public void setSolver(BiDirectSolvable solver) {
        this.solver = solver;
    }
    // some code
}

现在我想展示我的主要 class 片段,我在其中创建了 OneDirectPanel、BiDirectPanel 和 ISolver 的实例:

public class GUI {
    private ISolver solver;
    private MyAbstractPanel panelWithPicture;
    // a lot of code..
    if (comboBoxForMode.getSelectedItem().equals("one direct")) {
        solver = new OneDirectSolver();
        panelWithPicture = new OneDirectPanel();
        panelWithPicture.setSolver((OneDirectSolver)solver);
    } else {
        solver = new BiDirectSolver();
        panelWithPicture = new BiDirectPanel();
        panelWithPicture.setSolver((BiDirectSolvable)solver);
    }
}

我只看到一个解决方案:

if (comboBoxForMode.getSelectedItem().equals("one direct")) {
    OneDirectSolver solver = new OneDirectSolver();
    panelWithPicture = new OneDirectPanel();
    panelWithPicture.setSolver(solver);
} else {
    BiDirectSolvable solver = new BiDirectSolver();
    panelWithPicture = new BiDirectPanel();
    panelWithPicture.setSolver(solver);
}

但这对我来说是不可能的,因为我必须在求解器创建后对其进行一些操作。我必须在所有情况下都这样做。所以,我在 main class 中进行。 因此,在 main class 中,我必须声明类型为 ISolver 的引用。

更新: 最重要的是,如果我在 main class 中对解算器执行某些操作,它一定会影响 OneDirectPanel 和 BiDirectPanel 中的解算器。

由于您暂时需要更具体的运行时类型,您可以在之后分配给 this.solver

private ISolver solver;
...
if (comboBoxForMode.getSelectedItem()
                    .equals("one direct")) {
                OneDirectSolver solver = new OneDirectSolver();
                panelWithPicture = new OneDirectPanel();
                panelWithPicture.setSolver(solver);
                this.solver = solver;
            } else {
                BiDirectSolvable solver = new BiDirectSolver();
                panelWithPicture = new BiDirectPanel();
                panelWithPicture.setSolver(solver);
                this.solver = solver;
            }

首先,您可以将求解器实例作为 MyAbstractPanel 的 属性。这样你就有了一个基础求解器 属性。

    public abstract class MyAbstractPanel {

       private ISolver solver;

      public void setSolver(ISolver solver) {
         this.solver = solver;
      }

      public void someWork(){
         this.solver.someWork(); 
      }
     // implement this in child class
      public abstract void doSomeSpecificWork();

  }

    //assign solver object
    ISolver solver = new OneDirectSolver();

   public class BiDirectPanel extends MyAbstractPanel {
      public void doSomeSpecificWork(){
          ((OneDirectSolver)solver).doSomeSpecificWork();
     }
// some code

}

因为 solver 是面板的一个属性,我认为在你的 main class 中保留 ISolver 类型的引用不是一个好习惯。希望这有帮助。