Issue
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());
}
}
Solution
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
.
Answered By - Ma3x
Answer Checked By - Mildred Charles (JavaFixing Admin)