Reputation: 5351
I have interface:
public interface Doable {
void doSomething();
}
and the class that implements it:
public class DoJump() implements Doable {
@Override
private void doSomething() {
fireJumpHandler();
}
}
This is stupid example, but I would like to present the problem.
This code doesn't compile, I am getting an error in Eclipse IDE:
Cannot reduce the visibility of the inherited method from Doable
I have common interface that declares a method. This method is overriden in concrete class. I would like to avoid another class that can extend this class (DoJump
), so I would like to hide this method from sub classes. I would like to use private
modifier, but Java does not allow me to do it.
Why it is impossible, and how to workaround it?
Upvotes: 2
Views: 156
Reputation: 4091
Add final
to DoJump
declaration to prevent this class to be overriden (and therefore doSomething()
to be overriden too).
public final class DoJump implements Doable {
@Override
public void doSomething() {
fireJumpHandler();
}
}
If you still need to be able to inherit DoJump
but you don't want doSomething()
to be overriden, put the final
modifier in the method signature
public class DoJump implements Doable {
@Override
public final void doSomething() {
fireJumpHandler();
}
}
Upvotes: 2
Reputation: 25943
I'd like to answer your last question "How to workaround it?"
as this is not described in the related question. Create a second interface NotDoable
which simply does not have doSomething()
declared. Then let your DoJump
implement both interfaces. Give everyone that shouldn't override doSomething
a reference to the interface NotDoable
instead of the true type DoJump
. Then they won't know that the object truly can doSomething
, they won't know per class design. Of course, one can workaround this but one actually can workaround everything. The class design is more correct this way. Here's some code:
public interface Doable {
public void doSomething();
}
public interface NotDoable {
}
public class DoJump implements Doable, NotDoable {
@Override
public void doSomething() {
System.out.println("hi");
}
public NotDoable meAsNotDoable() {
return this;
}
public static void main(String[] args) {
DoJump object = new DoJump();
// This call is possible, no errors
object.doSomething();
NotDoable hidden = object.meAsNotDoable();
// Not possible, compile error, the true type is hidden!
hidden.doSomething();
}
}
But as said, one can workaround this by using if (hidden instanceof DoJump) { DoJump trueObject = (DoJump) hidden; }
. But well, one can also access private values via reflection.
Other classes now implement NotDoable
instead of extending DoJump
. If you declare everything others should know about DoJump
in this interface, then they only can do what they should do. You may call this interface IDoJump
and the implementing class DoJump
, a common pattern.
Now the same a bit more concrete.
public interface IDog {
public void bark();
}
public interface ICanFly {
public void fly();
}
public class FlyingDog implements IDog, ICanFly {
@Override
public void bark() {
System.out.println("wuff");
}
@Override
public void fly() {
System.out.println("Whuiiii");
}
public static void main(String[] args) {
FlyingDog flyingDog = new FlyingDog();
// Both works
flyingDog.fly();
flyingDog.bark();
IDog dog = (IDog) flyingDog;
// Same object but does not work, compile error
dog.fly();
ICanFly canFly = (ICanFly) flyingDog;
// Same object but does not work, compile error
canFly.bark();
}
}
And now an extending class.
public class LoudDog implements IDog {
@Override
public void bark() {
System.out.println("WUUUUFF");
}
// Does not work, compile error as IDog does not declare this method
@Override
public void fly() {
System.out.println("I wanna fly :(");
}
}
In the end, be aware that if others know that their IDog
actually is a FlyingDog
(and they cast it), then they must be able to call fly()
as a FlyingDog
must can fly. Furthermore, they must be able to override the behavior as long as they follow the specification of fly()
given by its method-signature
. Imagine a subclass
called PoorFlyingDog
, he needs to override the default behavior, else he can perfectly fly, but he is a poor flyer.
Summarized: Hide to others that you're actually a DoJump
, also hide that you are a Doable
, pretend to only be a NotDoable
. Or with the animals, pretend to only be an IDog
instead of a FlyingDog
or ICanFly
. If the others don't cheat (casting), they won't be able to use fly()
on you, though you actually can fly.
Upvotes: 3