Reputation: 1966
According to our professor, the use of protected visibility should be avoided at all costs. However, I'm a little puzzled as to why. Say We have this for example:
public abstract class Animal {
private int maxSpeed;
public Animal() {}
public abstract void setMaxSpeed();
}
Where each Animal
would have a max speed that would need to be defined later in the child class. However, throwing this in:
public class Tutrle extends Animal {
public Tutrle() {
}
@Override
public void setMaxSpeed() {
}
}
There is no way to be able to access the maxSpeed
variable from within the overridden setMaxSpeed()
method. Although a solution would be to set maxSpeed
via the constructor of the Animal
class, wouldn't be better to set the maxSpeed
variable to protected
and have it accessible to all child sub-classes to be defined later?
Upvotes: 2
Views: 2349
Reputation: 34460
In order to access maxSpeed
attribute from subclasses, you could:
protected
(your professor doesn't seem to like this very much, but I think he's lacking a suitable explanation)getMaxSpeed()
method in the superclass: if knowing the max speed from outside the hierarchy is needed, declare it as public
; otherwise, declare it as protected
, so that subclasses (specific animals, such as your Turtle
) can know what their max speed is.I agree with @Eran in that the setMaxSpeed()
method shouldn't be declared as abstract
in the Animal
superclass, and subclasses could call super.setMaxSpeed()
from their own setMaxSpeed
method if they need to do specific processing when their max speed is being set.
Regarding why using protected
is claimed to be 'avoided at all costs', or dangerous, etc, please refer to this amazing newsletter's article. My personal opinion is that it is wrong to make such claims, or at least, an overreaction. However, as explained in the article:
We should try to only call either private or final methods from inside our constructors. The reason is that Java always calls the most derived method, which means we could call a method on a half-initialized object.
This means that if you call a protected
method from within the constructor of your superclass, and that if the protected
method is overriden in one of the subclasses, then the code within that method would run before the rest of the class was fully initialized, which might lead to nasty errors:
class Animal {
protected int maxSpeed;
protected SomeClass someClass;
protected Animal(int maxSpeed, SomeClass someClass) {
this.setMaxSpeed(maxSpeed); // call to subclass method
this.someClass = someClass;
}
public abstract void setMaxSpeed(int maxSpeed); // could also be protected
}
class Turtle extends Animal {
@Override
public void setMaxSpeed(int maxSpeed) {
if (this.someClass.checkIfMaxSpeedMustBeDoubled()) { // throws NPE
this.maxSpeed = maxSpeed * 2;
} else {
this.maxSpeed = maxSpeed;
}
}
}
In this very simple example, this.someClass.checkIfMaxSpeedMustBeDoubled()
throws a NullPointerException
because this.someClass
has not been yet initialized in the Animal
superclass. This kind of error is very common when using protected
members, but claiming that protected
should be avoided is ridiculous. Just be careful and only call either private
or final
methods from within the superclass' constructor, and you'll be OK.
Upvotes: 1
Reputation: 393821
Since the maxSpeed
member is defined in the Animal
class, it makes more sense for that class to have a non-abstract method that would set it :
public void setMaxSpeed(int maxSpeed)
{
this.maxSpeed = maxSpeed;
}
The sub-classes (such as Turtle
) may override this method to add logic, but they should call the base class to set the value.
@Override
public void setMaxSpeed(int maxSpeed)
{
if (maxSpeed > 5)
throw new SomeException();
super.setMaxSpeed(maxSpeed);
}
If setMaxSpeed()
stays abstract, it would make more sense for each sub-class that implements this method to have its own maxSpeed
member.
Upvotes: 2
Reputation: 5023
It is depends on requirement, If you want maxSpeed
variable should be present in your all subclasses then put that variable in super class and then reuse that variable in subclass. for that you have to initialize that variable through subclass constructor and change modifier to protected for that variable.
But its better to create variable in your subclass if those are related to your subclass only,
Upvotes: 0