GeordiLaForge
GeordiLaForge

Reputation: 23

Polymorphism with parameters of child types in Java

I have a java programming related problem. I have the following classes:

public abstract class Animal {
    abstract void walk(AbstractWalkData abstractWalkData);
}

public class Mouse extends Animal{
    @Override
    void walk(AbstractWalkData abstractWalkData) {
        System.out.println(abstractWalkData.getWalkSound());
        System.out.println(abstractWalkData.getWalkSpeed());
        System.out.println(((MouseWalkData) abstractWalkData).getMouseSpecific());

    }
}

public class Tiger extends Animal{
    @Override
    void walk(AbstractWalkData abstractWalkData) {
        System.out.println(abstractWalkData.getWalkSound());
        System.out.println(abstractWalkData.getWalkSpeed());
        System.out.println(((TigerWalkData) abstractWalkData).getTigerSpecific());
    }
}

@Data
@SuperBuilder
public abstract class AbstractWalkData {
    private String walkSound;
    private int walkSpeed;
}

@Getter
@Setter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class MouseWalkData extends AbstractWalkData {
    private String mouseSpecific;
}

@Getter
@Setter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class TigerWalkData extends AbstractWalkData {
    private String tigerSpecific;
}

public class MainClass {
    public static void main(String[] args) {
        Animal mouse = new Mouse();
        MouseWalkData mouseData = MouseWalkData.builder()
                .walkSound("mouse walk sound")
                .walkSpeed(5)
                .mouseSpecific("mouse specific string")
                .build();
        mouse.walk(mouseData);
        Animal tiger = new Tiger();
        TigerWalkData tigerWalkData = TigerWalkData.builder()
                .walkSound("tiger walk sound")
                .walkSpeed(8)
                .tigerSpecific("tiger specific string")
                .build();
        tiger.walk(tigerWalkData);
    }
}

Note that I am using lombok to get rid of boilerplate code. Is there any way to get rid of the castings in the walk method of the Mouse and Tiger class? I would like to do something like this:

public class Mouse extends Animal{
    @Override
    void walk(MouseWalkData mouseWalkData) {
        System.out.println(mouseWalkData.getWalkSound());
        System.out.println(mouseWalkData.getWalkSpeed());
        System.out.println(mouseWalkData.getMouseSpecific());

    }
}

But i get a compiler error. Thank you all for any ideas.

Upvotes: 2

Views: 327

Answers (2)

Tugrul Bayrak
Tugrul Bayrak

Reputation: 111

You can use 'instanceof' keyword to do that in Java. If you use concrete classes as parameter in your walk method as you mentioned, it is not polymorphism anymore. You should use an abstract class or interface in the parameter. Then pass any concrete child object to that method.

if(abstractWalkData instanceof MouseWalkData) {
   System.out.println((MouseWalkData)abstractWalkData.getMouseSpecific());
}

Upvotes: 0

Karim
Karim

Reputation: 1034

That's how Java works but what you can do is start using generics in your code, for example, it will be something like this

abstract class Animal <T extends AbstractWalkData > {
    abstract void walk(T walkData);
}

and then, for example, your mouse class will be something like this

public class Mouse extends Animal <MouseWalkData>{
    @Override
    void walk(MouseWalkData mouseWalkData) {
        System.out.println(mouseWalkData.getWalkSound());
        System.out.println(mouseWalkData.getWalkSpeed());
        System.out.println(mouseWalkData.getMouseSpecific());

    }
}

and it will work

to learn more about generics I recommend to read about them and how it helped to avoid some of java's boilerplate code https://www.baeldung.com/java-generics

Upvotes: 2

Related Questions