Search code examples
javagenericspolymorphism

Java polymorphism pointers


I've been studying java a little bit and I've come upon a problem I couldn't solve (I did research but since it's a pretty specific question no answer was found):

I'm trying to add variables and methods that would be inherited by classes in the same way an interface does it (have a class inherited by different classes that already have an ancestor, i.e.: Actor extends Character and Weapon extends Item, I need both Actor and Weapon to have XY coordinates, width/height and move() method)

At first I thought Interfaces were the solution, but since they are 100% abstract, I would need to redefine the methods every time, which, to me, beats the purpose of inheritance in this case.

I have thought about making a superior parent (like MovableObject) at the root of the ancestry tree which would include both the Item and Actor classes, but since they are so different in every other way it feels counter logic to have them in the same ancestry tree.

Edit

Thank you all for your responses, I said I'd update when I tried it, and I did but now I realize my whole code is going to need a lot of refactoring so I can't tell you if it works or not right away. Although it did solve my problem since I at least have something to work towards.


Solution

  • The language constructs that you can use are either interfaces or abstract classes.

    • Interfaces: define common behavior across unrelated objects (for example, objects that can be serialized, objects that can be compared, etc).
    • Abstract classes: define common behavior across a hierarchy of objects (for example, it would make sense to define a method getPrice in Item and inherit that in Weapon).

    In your example, methods such getWidth(), getHeight(), getX() and getY() are good candidates for interfaces (since they share some common traits between unrelated objects).

    // Another way to share this state would be via a Point interface and 
    // aggregating two point objects in your Item and Character classes
    interface Coordinates {
    
        double getX1();
    
        double getY1();
    
        double getX2();
    
        double getY2();
    
    }
    
    interface Dimension {
    
        double getWidth();
    
        double getHeight();
    
    }
    

    I don't know your whole context, but are you sure you need both coordinates and dimensions (I think you could determine the width and height from the X and Y)?

    Those interfaces should be implemented by both of your ancestor classes (Character and Item) and inherited through the hierarchy. Do not add a common ancestor between Character and Item just so you can avoid implementing getX and getY twice.

    Regarding the move method, I think it's another responsibility and you should define it somewhere else.

    // Not necessarily the right name
    class MoveHelper {
    
        // You can pass either a Character or an Item here
        // since both implement Coordinates
        // Not necessarily the right signature
        void move (Coordinates object)
    
    }
    

    Depending on how you chose to design your solution, the move method can become a static somewhere or an object that you would aggregate in both Character and Item and delegate to it for the move implementation.

    As a final note, consider that you can achieve reuse via either inheritance (interfaces and abstract classes) or composition (what you would do if you would aggregate the MoveHelper and delegate to it for the move implementation in Character and Item).

    Hope this helps!