Search code examples
javagenericsinheritancehierarchy

Inheritance hierarchy altering to reduce code duplication


I'm experiencing difficulties setting up the structure of my code. In one project, I have two classes LeftCell and RightCell, both extending class Cell. Now, to avoid code duplication, I want to use these objects in multiple other projects. The problem is that I also want to add extra functionalities to these objects (the Cell object in particular), which differ per project.

Suppose I create a new project in which I want to visualize Cell objects using a void draw() method. My first thought was to create a new CellProject1 class that extends the Cell class and includes the draw() method:

class CellProject1 extends Cell {
    void draw() {}
}

The problem is that any LeftCell/RightCell objects I create, do of course not have access to this draw() method. I guess I want to somehow squeeze a Cell subclass in the class hierarchy such that it changes from:

Cell
    LeftCell
    RightCell

to:

Cell
    CellProjectX
        LeftCell
        RightCell

depending on the project I'm running. I played around with generics, but can't get it to work. All suggestions are welcome!


Solution

  • The problem is that any LeftCell/RightCell objects I create, do of course not have access to this draw() method.

    A method specific to a child class can not of course be invoked on a parent instance that doesn't know it.

    Since your requirement is

    Inheritance hierarchy altering to reduce code duplication In one project, I have two classes LeftCell and RightCell, both extending class Cell. Now, to avoid code duplication, I want to use these objects in multiple other projects

    I think that you should make things a little different.

    If you want to avoid exploding the number of combination possible of classes and not duplicating LeftCell and RightCell like in your example :

    Cell
        CellProjectX
            LeftCell
            RightCell
    

    that could be finally completed by :

    Cell
        CellProjectY
            LeftCell
            RightCell
    
    Cell
        CellProjectZ
            LeftCell
            RightCell
    

    you should favor the composition over the inheritance to create your specific project Cell implementations.

    For the common Cell structures:

    The Cell subclass could be a Cell interface that define common methods for any Cell and you could have a AbstractCell class that defines common implementation for it.

    public interface Cell{
       int getValue();
       void setValue(int value);
    }
    
    
    public abstract class AbstractCell implements Cell{
          ...
    }
    

    Then you could define the RightCell and LeftCell by extending AbstractCell :

    public class RightCell extends AbstractCell {
          ...
    }
    
    public class LeftCell extends AbstractCell {
          ...
    }
    

    For the Cell implementations specific to a project :

    Now in a specific project you could a create a custom Cell implementation by composing it with a Cell instance (finally a LeftCell or RightCell instance) that will under the hood be used to implement the Cell interface in the specific project concrete class.
    In the specific implementation, you could of course add any required method specific to the project.
    For example :

    class CellProject1 implements Cell {
    
       private Cell cell;
    
       CellProject1 (Cell cell){
          this.cell = cell;
       }
    
       public int getValue(){
          cell.getValue();
       } 
    
       public void setValue(int value){
          cell.setValue(value);
       }
    
       public void draw(){
       ...
       }
    
    }
    

    You can so create CellProject1 instances like that :

    CellProject1 leftCell = new CellProject1(new LeftCell());
    CellProject1 rightCell = new CellProject1(new RightCell());
    leftCell.draw();
    rightCell.draw();
    

    And in another project that uses CellProject2 instances with a specific write()method, you could write :

    CellProject2 leftCell = new CellProject2(new LeftCell());
    CellProject2 rightCell = new CellProject2(new RightCell());
    leftCell.write();
    rightCell.write();