8 Clases e interfaces selladas¶
Introducción¶
Una jerarquía de clases nos permite reutilizar el código mediante la herencia. Sin embargo, la jerarquía de clases también puede cumplir otros propósitos. La reutilización del código es excelente, pero no siempre es nuestro objetivo principal.
Un propósito alternativo de una jerarquía de clases puede ser modelar varias posibilidades que existen en un dominio.
Como ejemplo, imaginemos un dominio empresarial que solo trabaja con automóviles y camiones, no con motocicletas. Al crear la clase abstracta Vehicle
en Java, deberíamos poder permitir que solo las clases Car
y Truck
la extiendan. Por lo tanto, queremos asegurarnos de que no se haga un uso indebido de la clase abstracta Vehicle
dentro de nuestro dominio.
En este ejemplo, nos interesa más la claridad del código que maneja subclases conocidas que la defensa contra todas las subclases desconocidas .
En versiones anteriores, Java proporcionaba opciones limitadas en el área de control de herencia.
Una clase final
no puede tener subclases. Una clase friendly
solo puede tener subclases en el mismo paquete.
Una superclase desarrollada con un conjunto de sus subclases debería poder documentar su uso previsto, sin restringir sus subclases. Además, tener subclases restringidas no debería limitar la accesibilidad de su superclase.
Sealed¶
Una clase o interfaz sellada (sealed) permite crear una clase o interfaz que solo puedan ser heredadas por las clases que el mismo programador que las crea, permite.
Las clases e interfaces selladas, fueron añadidas en su versión alpha en la versión 15 de Java, y de forma estable en la versión 17.
Para crear una clase o interfaz sellada, se usa el modificador de acceso sealed
seguido del nombre la clase o interfaz. Luego, se usa el modificar permit
seguido del nombre de las clases o interfaces que pueden heredar o implementar dicha clase.
Veamos un ejemplo
Ahora, al crear la clase Car
o Truck
ambas pueden heredar de la clase Vehicle
y/o implementar la interface Service
:
Sin embargo, una clase diferente a Car
o Truck
no podrá ni heredar ni implementar la clase o interfaz sellada:
Clase permitida¶
Una clase o interfaz permitida es aquella a la que se le permite heredar o implementar una clase o interfaz sellada. Sin embargo, esto debe tener una restricción, ya que si Vehicle
permite que la clase Car
pueda heredar de ella, no es una buena práctica que cualquier otra clase pueda heredar de la clase Car
.
Para ello, la sealed class o sealed interface requieren de forma obligatoria que la clase o interfaz heredada o implementada utilice un modificador de acceso, final
, sealed
o non-sealed
.
Si la clase o interfaz permitida utiliza el modificador de acceso final
, esta clase no puede tener herencia. Por lo que, estaríamos evitando que cualquier otra clase o interfaz no permitida herede o implemente de nuestra clase o interfaz sellada.
Por otro lado, si una clase o interfaz utiliza el modificar sealed
también quedará sellada, por lo que podrán heredar o implementar de ella, las clases que ésta permite.
También se puede utilizar el modificador non-sealed
. En este caso, la clase permitida también permite su implementación y su extensión:
Ejercicio
Crea una clase sellada Shape
que permita su implementación en la clase Circle
, Square
y Triangle
. Teniendo en cuenta las siguientes restricciones:
- La clase
Circle
no permitirá ninguna tipo de herencia. - La clase
Square
permitirá herencia únicamente de la claseRectangle
. - Cualquier clase puede heredar de la clase
Triangle
.