How do i deny access to a method of a superclass
I was wondering how i could deny access to a method of the superclass of a class?
Example: I have a class Door, and a class Emptyness, which is basicly just an open door for my application, now i want to inherit most of the doors methods but i dont want the user to be able to call the 'close door' method on emptynes开发者_Go百科s, how can i do that?
We obviously can't reduce visiblity on overriding a method. If the close door method on Door
is public
, the overriden method in Emptyness
can't be private...
A usual approach is to override the close door method in Emptyness
and simply do nothing or thrown some UnsupportedOperationException
(like implementors of Iterator
do, if they don't allow removing an element).
Example:
public class Door {
public void closeDoor() {
// closing door actions
}
}
public class Emptyness extends Door {
@Override void closeDoor() {
// do nothing or
throw new UnsupportedOperationException("Can't close door on Emptyness");
}
}
It sounds like Emptyness
fails the "should I be a subclass" test with regard to Door
. The test is that the following sentence is true: Emptyness
is a Door
. Since Door
can be closed, Emptyness
doesn't meet that requirement.
Recommend using aggregation rather than inheritance. Have Emptyness
implement its own interface (or some other relevant interface, but not Door
) and contain a Door
instance that it uses to satisfy relevant operations.
Doing something like overriding the close
operation to do nothing or to throw an exception is completely inappropriate unless Door#close
is defined as being optional (via a throws
tag for the relevant exception). (And beware of "optional" operations in class hierarchies, they usually indicate a design problem. Not necessarily always, but usually.) The example Andreas gives of Iterator#remove
, for instance: Iterator#remove
is tagged as throwing an UnsupportedOperationException
. If Door#close
is tagged that way, and if you're comfortable with that way of doing things, great, you're there. But if it doesn't, then Emptyness
is failing to honor the Door
contract, which usually means you need to go another way.
Why not use Designer Pattern. Since the closeDoor method is not common to all the sub classes of Door, then it should not be present in Door class at all, rather make an interface with name Closable with a close method, implement that interface in some classes like ClosableTrue and ClosableFalse. Now make a reference variable in the Door class of type Closable and initialize it in the constructor of the class with an object of ClosableTrue or ClosableFalse depending on the type of argument passed to the constructor. Now whenever the close method is called on any object of Door or a subclass of Door, the method that will be called will be the one whose class was used to initialize the constructor of Door. You can implement the close method of ClosableFalse class with no meaningfull functionality.
Make that private in class Door. Because if you have public or protected in super class then you cannot have a more restrictive access modifier in the downwards hierarchy. So you cannot make private in Empty class, rather you have to in Door class.
There are a lot of options. Pick whichever fits your needs
- Make the method
private
Make the method
final
so that it can't be overridden and also add the logic checking if the method is getting called from aninstanceof
Emptiness then throw an exception.public class Emptiness extends Door{ public static void main(String[] args) throws Exception { Door x = new Emptiness(); x.somemethod(); } }
Door Class
public class Door { final public void somemethod() throws Exception{ if(this instanceof Emptiness){ throw new Exception(); } } }
精彩评论