Disabling inherited method on derived class
Is there any way to, in a Java derived class, "disable" a method and/or field that is otherwise inherited from a base class?
For example, say you have a Shape
base class that has a rotate()
method. You also have various types derived from the 开发者_如何学JAVAShape
class: Square
, Circle
, UpwardArrow
, etc.
Shape
has a rotate()
method. But I don't want rotate()
to be available to the users of Circle
, because it's pointless, or users of UpwardArrow
, because I don't want UpwardArrow
to be able to rotate.
I don't think it is possible. However you can further refine the Shape class by removing the rotate() method from its specification and instead define another subclass of Shape called RotatableShape and let Circle derive from Shape and all other Rotatable classes from RotatableShape.
e.g:
public class Shape{
//all the generic methods except rotate()
}
public class RotatableShape extends Shape{
public void rotate(){
//Some Code here...
}
}
public class Circle extends Shape{
//Your implementation specific to Circle
}
public class Rectangle extends RotatableShape{
//Your implementation specific to Rectangle
}
You can override the specific method "rotate()" in the class you want to disable this operation, like this
public void rotate() {
throw new UnsupportedOperationException();
}
You have a bad class heirarchy if you need to disable methods in child classes. Any subclass should be able to smoothly use the methods of its superclasses. This is called the "Liskov Substitution Principle" (https://en.wikipedia.org/wiki/Liskov_substitution_principle). You can read more about this in this thread: https://softwareengineering.stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses.
Do what Chandu suggests. Don't put rotate() in Shape. Instead, make a subclass of Shape called RotatableShape, and put rotate() in there. Then Circle can inherit from Shape, and Rectangle can inherit from RotatableShape.
No.
- you can pull the method down in only the
Circle
class (or an interface that is implemented only by that class) - you can provide an empty implementations or ones that throw
UnsupportedOperationException
in the classes that do not support it.
Declaring the same function in the 'child'-class will overwrite the default function declared in the base class. So in your child-class, make a function called rotate()
which does nothing, that will overwrite the default behaviour
Can you use an empy (does nothing) method for the circle? For the arrow I would reconsider object hierarchy
One way to deal with this is to define a second method called (say) boolean isRotatable()
, and use this to determine whether the rotation controls are made available to the user.
Another option would be to introduce a Rotatable
interface and use shape instanceof Rotatable
to make the determination. (However, I think the isRotatable()
approach is more flexible.)
In either case, you can implement the rotate()
method on a class that should never be rotated as:
public void rotate() {
throw new UnsupportedOperationException("rotate");
}
The Java language doesn't provide a way to "remove" or "disable" a method in a subclass. That would violate the substitutability principle and would break polymorphism. A subclass cannot remove visible members from the parent classes API.
I don't think you can disable a method in the way you suggest.
In your example, lets say you have a method that takes a Shape
public void handleShape(Shape s){
s.rotate();
}
Then you pass a Circle to this method
handleShape(new Circle());
What should happen? Essentially you are asking for a fundamental change to Java's type system.
If Circle is a Shape and shouldn't be rotated then it probably means that Shape was designed poorly and shouldn't have a rotate method. You can add rotate to a different class int the hierarchy like, RotatableShape or possibly use an interface Rotatable.
So there are two possibilities here. One is that you have an object that can rotate, but shows no change in the process. The other is that you have an object that is defined by it's direction. Each ought to be handled separately and in their own way.
So for circle, we have a stub for a rotate function since there is no change in the system. Don't like it, too bad. I'm putting off my quiz on point groups to write this.
For upward arrow, we throw an exception since we don't want to drive the wrong way on a one-way street and this ought to be constant anyway.
In my case, I'm defining a point in 3 dimensional space by inheriting operations from a class defining a quaternion. The 3 dimensional point only uses the 3 imaginary coordinates of the quaternion and if the quaternion has a non-zero value for the real component, it will ruin the vital operations of the rendering algorithm inherited from the quaternion via the 3 dimensional coordinate.
Excuse me for being overly philosophical, however, this question raises a valid point in CS about how this should be handled. As Stephen notes, being able to hide, disable or remove the inherited function in the child class "...would violate the substitutability principle and would break polymorphism."
My case falls under the upward arrow, except I'm pointing into imagination. I am attempting to truncate a derived class, which means any 'grandchild' class (possibly inheriting spin operators) would no longer necessarily be quaternions. It would be more elegant to avoid resorting to throwing exceptions, by trimming the base class at the typecast for a truncating derived class. The alternative would be defining the 3 dimensional coordinate as a separate class with a quaternion member variable; the drawback is that the implementation has too much glue.
Then I can put the new spin operations into the derived class for the 3 dimensional coordinates for the three planes (ij, jk, ik) and then the objects with 3d vertices can be rotated via a loop and an identical member function call for each vertex. You might could keep track of the symmetry on your own, before you start rotating the points defining the surface of sphere, which is why you need to use the stub function and possibly implement your own 'constant' flag.
I needed the same thing for a custom alertdialog. I needed to pass an argument that became available only at the show moment, so I implemented my show(argument) method, but show() worked too because of the superclass. There was a risk of that I could invoke myDlg.show()
by accident, without an argument, and that would cause a crash. To make sure the superclass method is never called outside my CustomAlertDialog class, I added the method private static void show(){}
to it. That's it.
So, to disable a supermethod, make it private and static in the subclass. In your case, it would be:
private void rotate(){}
There is a possibility and it's quite simple. Instead of inheritance use composition:
public class Shape{
public method1();
public method2();
public rotate();
public method3();
}
public class Circle{
private Shape shape;
public Circle(){
this.shape = new Shape();
}
public method1(){
shape.method1()
}
public method2(){
shape.method2()
}
public method3(){
shape.method3()
}
}
精彩评论