Skip to content
Advertisement

Two classes and one method with different implementation for each of them

I’m just starting to learn OOP in Java, so this might be a dumb question. The Cat class extends Animal, they have a constructor, a static array, a method that fills the array, and a method that creates an object of the Moving class. On this created object of class Moving, the walk() method can be invoked. Question: how to write different behavior in the walk () method, depending on how the object was created (who was the creator Animal or Cat)? I was thinking of writing a separate efficiency() method to use in the walk() method, and put it in the Animal class and override this method in the Cat class. But in the walk() method, I can only use the static method of the Animal class and I can’t override it for the Cat class.

If in Main I create Animal noName = new Cat(), then the program should call Cat.efficiency(). If I create Animal noName = new Animal(), then the Animal.efficiency() method must be called. Something like this, I think. Is it possible?

public class Animal {
    private int capacity;
    public static int[] animalArray;

    public Animal(int value) {
        animalArray = new int[value];
    }

    public boolean adSteps(int element){
        if (capacity >= animalArray.length) {
            return false;
        } else {
            animalArray[capacity++] = element;
        }
        return true;
    }

    public Moving letsMove() {
        return new Moving();
    }
    public static int efficiency(int steps){
        int equalSteps = steps+10;
        return equalSteps;
    }
}



public class Cat extends Animal{
    public Cat(int value) {
        super(value);
    }
    public static int efficiency(int steps) {
        int equalSteps = steps + 50;
        return equalSteps;
    }
}



public class Moving {
    private int[] movingArray = Animal.animalArray.clone();
    private int totalWay;
    
    public int walk(){
        System.out.println("Go ahead");
        for (int i = 0; i < movingArray.length; i++){
            totalWay += movingArray[i];
        }
        totalWay = Animal.efficiency(totalWay);
        return totalWay;
    }
}



public class Main {
    public static void main(String[] args) {

        Animal noName = new Cat(3);

        noName.adSteps(5);
        noName.adSteps(3);
        noName.adSteps(2);

        Moving iAmMoving = noName.letsMove();

        System.out.println(iAmMoving.walk());
    }
}

Advertisement

Answer

Overriding the efficiency method

If you want to be able to override your efficiency method in a subclass (in the Cat class), you need to make it an instance method instead of a static method.

So you would remove the static keyword from the efficiency method in the Animal class

public class Animal {
    // ...

    public int efficiency(int steps) {
        int equalSteps = steps + 10;
        return equalSteps;
    }
}

You would do the same in the Cat class but here you would also add the @Override annotation

public class Cat extends Animal {
    @Override
    public int efficiency(int steps) {
        int equalSteps = steps + 50;
        return equalSteps;
    }
}

Now the compiler will start complaining that the Moving class cannot access efficiency because the method cannot be called as a static method anymore. Now the Moving class needs an instance of the Animal class to be able to call the efficiency method.

public class Moving {
    private int[] movingArray = Animal.animalArray.clone();
    private int totalWay;
    // Add an instance field to store the reference
    private Animal animal;

    // Add a constructor to pass the reference
    public Moving(Animal animal) {
        this.animal = animal; // store it here to use it later
    }

    public int walk(){
        System.out.println("Go ahead");
        for (int i = 0; i < movingArray.length; i++){
            totalWay += movingArray[i];
        }
        // use the reference here to be able to call the method
        totalWay = animal.efficiency(totalWay);
        return totalWay;
    }
}

And now the compiler will complain that new Moving() is not a constructor anymore, so you have to do another change

public Animal {
    // ...
    public Moving letsMove() {
        return new Moving(this);
    }
    // ...
}

Potential issue: Static storage for instance related data?

Using a static array animalArray (to which all Animal instances are adding values) to store data that belongs to each individual Animal instance won’t produce correct results when calculating total steps for each Animal.

With your current example code it will work as you probably expect it to, but as soon as you will create another Animal instance (or another Cat instance) you will probably get unexpected results.

If your goal is to hold/store state that belongs to an instance, you want to use a non-static field for that. You would do the same as shown above for the efficiency method. Remove the static keyword from the animalArray field and change the code where it is accessed to use instance access instead of static access.

It seems the array is storing steps, so it would be less confusing if it would be called stepsArray instead of animalArray.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement