java - polimorfismo - herencia poo
Deshabilitar el método heredado en la clase derivada (10)
¿Hay alguna forma de, en una clase derivada de Java, "deshabilitar" un método y / o campo que de otra manera se hereda de una clase base?
Por ejemplo, supongamos que tiene una clase base de Shape
que tiene un método rotate()
. También tienes varios tipos derivados de la clase de Shape
: Square
, Circle
, UpwardArrow
, etc.
Shape
tiene un método rotate()
. Pero no quiero que rotate()
esté disponible para los usuarios de Circle
, porque no tiene sentido, o los usuarios de UpwardArrow
, porque no quiero que UpwardArrow
pueda rotar.
¿Puedes usar un método de empy (no hace nada) para el círculo? Para la flecha reconsideraría la jerarquía de objetos.
Así que aquí hay dos posibilidades. Una es que tiene un objeto que puede rotar, pero no muestra ningún cambio en el proceso. La otra es que tienes un objeto que está definido por su dirección. Cada uno debe ser manejado por separado y a su manera.
Así que para el círculo , tenemos un código auxiliar para una función de rotación, ya que no hay cambios en el sistema. No me gusta, muy mal. Pongo mi cuestionario sobre grupos de puntos para escribir esto.
Para la flecha hacia arriba , lanzamos una excepción ya que no queremos conducir por el camino equivocado en una calle de un solo sentido y esto debería ser constante de todos modos.
En mi caso, estoy definiendo un punto en el espacio tridimensional al heredar operaciones de una clase que define un cuaternión. El punto tridimensional solo usa las 3 coordenadas imaginarias del cuaternión y si el cuaternión tiene un valor distinto de cero para el componente real, arruinará las operaciones vitales del algoritmo de representación heredado del cuaternión a través de la coordenada tridimensional.
Discúlpeme por ser demasiado filosófico, sin embargo, esta pregunta plantea un punto válido en CS sobre cómo se debe manejar esto. Como señala Stephen, ser capaz de ocultar, deshabilitar o eliminar la función heredada en la clase secundaria "... violaría el principio de sustituibilidad y rompería el polimorfismo".
Mi caso cae debajo de la flecha hacia arriba, excepto que estoy apuntando a la imaginación. Estoy tratando de truncar una clase derivada, lo que significa que cualquier clase ''nieta'' (posiblemente heredando operadores de giro) ya no será necesariamente cuaterniones. Sería más elegante evitar el recurso a excepciones de lanzamiento, recortando la clase base en el encasillado para una clase derivada truncadora. La alternativa sería definir la coordenada tridimensional como una clase separada con una variable miembro de cuaternión; El inconveniente es que la implementación tiene demasiado pegamento.
Luego puedo colocar las nuevas operaciones de giro en la clase derivada para las coordenadas tridimensionales de los tres planos (ij, jk, ik) y luego los objetos con vértices 3d pueden rotarse a través de un bucle y una función de miembro idéntica para cada vértice. . Podría seguir la simetría por su cuenta, antes de comenzar a rotar los puntos que definen la superficie de la esfera, por lo que necesita usar la función de código auxiliar y posiblemente implementar su propia bandera "constante".
La declaración de la misma función en la clase ''child'' sobrescribirá la función predeterminada declarada en la clase base. Entonces, en su clase hija, haga una función llamada rotate()
que no haga nada, que sobrescriba el comportamiento predeterminado
Necesitaba lo mismo para un diálogo de alerta personalizado. Necesitaba pasar un argumento que estaba disponible solo en el momento del show, así que implementé mi método show (argumento), pero show () también funcionó debido a la superclase. Hubo un riesgo de que pudiera invocar myDlg.show()
por accidente, sin una discusión, y eso causaría un bloqueo. Para asegurarse de que el método de superclase nunca sea llamado fuera de mi clase CustomAlertDialog, le agregué el método private static void show(){}
. Eso es.
Entonces, para deshabilitar un método superior, conviértalo en privado y estático en la subclase. En tu caso, sería:
private void rotate(){}
No creo que puedas deshabilitar un método de la forma que sugieres.
En tu ejemplo, digamos que tienes un método que toma una Forma
public void handleShape(Shape s){
s.rotate();
}
Entonces pasas un círculo a este método.
handleShape(new Circle());
¿Qué debería pasar? Esencialmente estás pidiendo un cambio fundamental en el sistema de tipos de Java.
Si el Círculo es una Forma y no debe rotarse, entonces probablemente significa que la Forma fue mal diseñada y no debería tener un método de rotación. Puede agregar rotar a una clase diferente como la jerarquía, RotatableShape o, posiblemente, utilizar una interfaz Rotatable.
No creo que sea posible. Sin embargo, puede refinar aún más la clase de Forma eliminando el método rotate () de su especificación y, en su lugar, definir otra subclase de Forma llamada RotatableShape y dejar que Circle se derive de Shape y todas las demás clases de RotatableShape .
p.ej:
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
}
No.
- puede bajar el método solo en la clase
Circle
(o en una interfaz implementada solo por esa clase) - puede proporcionar implementaciones vacías o las que arrojan
UnsupportedOperationException
en las clases que no lo admiten.
Puede anular el método específico "rotate ()" en la clase que desea deshabilitar esta operación, como esto
public void rotate() {
throw new UnsupportedOperationException();
}
Tiene una jerarquía de clases incorrecta si necesita deshabilitar métodos en clases secundarias. Cualquier subclase debería poder usar sin problemas los métodos de sus superclases. Esto se denomina "Principal de sustitución de Liskov" ( https://en.wikipedia.org/wiki/Liskov_substitution_principle ). Puede leer más sobre esto en este hilo: https://softwareengineering.stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses .
Haz lo que Chandu sugiere. No ponga rotate () en forma. En su lugar, cree una subclase de Forma llamada RotatableShape y coloque rotate () allí. Luego, Circle puede heredar de Shape, y Rectangle puede heredar de RotatableShape.
Una forma de lidiar con esto es definir un segundo método llamado (digamos) boolean isRotatable()
, y usarlo para determinar si los controles de rotación están disponibles para el usuario.
Otra opción sería introducir una interfaz Rotatable
y utilizar la shape instanceof Rotatable
para tomar la decisión. (Sin embargo, creo que el enfoque isRotatable()
es más flexible).
En cualquier caso, puede implementar el método rotate()
en una clase que nunca debe rotarse como:
public void rotate() {
throw new UnsupportedOperationException("rotate");
}
El lenguaje Java no proporciona una forma de "eliminar" o "deshabilitar" un método en una subclase. Eso violaría el principio de sustituibilidad y rompería el polimorfismo. Una subclase no puede eliminar miembros visibles de la API de clases padre.