TSM - Java prin exemple (II) – clasele sealed

Ovidiu Mățan - Fondator @ Today Software Magazine


Java 17 ne aduce câteva lucruri noi printre care și sealed classes. Acestea îmbunătățesc limbajul prin faptul că reprezintă o modalitate de a restricționa accesul la extinderea unei clase. Desigur, aveam pentru aceasta opțiunea marcărilor ca final sau limitările prin modificatorii de acces protected ori private. Avantajul claselor sealed constă în controlarea mai ușoară a cine are dreptul de a o extinde.

Clasele sealed

Ne permite să definim lista de clase care pot să extindă clasa curentă. Folosim keywordul permits pentru a defini această listă. La rândul lor, clasele copil pot să fie de tipul:

Fig. 1. Sursa: https://learning.oreilly.com/library/view/ocp-oracle-certified/9781119864585/c07.xhtml#R_c07-fig-0005

public sealed class Article 
  permits TechnicalArticle, 
          AbstractArticle, 
          ManagementArticle{}

public final class TechnicalArticle  
  extends Article{}

public non-sealed class 
  AbstractArticle extends Article{}

public sealed class ManagementArticle 
 extends Article permits AgileArticle

public final class AgileArticle 
  extends ManagementArticle

public class PoliticalArticle 
  extends AbstractArticle

Fig. 2.

Așa cum se vede în acest exemplu, avem clasa sealed Article extinsă de TechnicalArticle (clasă finală), AbstractArticle este non-sealed, iar prin ea ne apare PoliticalArticle. Ultima clasă este ManagementArticle (sealed) extinsă de clasa finală AgilArticle.

Trebuie menționat că în toată ierarhia, PoliticalArticle extinde într-un fel nedorit AbstractArticle. Soluția finală ar putea fi excluderea AbstractArticle din lista de clase permise. Ideal ar fi însă să putem specifica printr-o adnotare dacă permitem sau nu clase non-sealed în ierarhia Article.

Simplificare

În cazul în care toate clasele sealed și copii ce o moștenesc sunt în același fișier, menționarea listei permits devine opțională iar definiția acestora devine următoarea:

sealed class Article{}

final class TechnicalArticle 
  extends Article {}

non-sealed class AbstractArticle 
  extends Article{}

class PoliticalArticle 
  extends AbstractArticle{}

sealed class ManagementArticle {}

final class AgileArticle 
  extends ManagementArticle {}

Interfețe

Putem aplica constrângerile sealed și interfețelor. Diferența față de clase este aceea că în clauza permits vom putea menționa atât alte interfețe ce pot să o extindă pe cea curentă, cât și clase care o pot implementa.

public sealed interface Article 
  permits TechnicalArticle, 
          AbstractArticle, 
          ManagementArticle {}

public final class TechnicalArticle 
  implements Article {}

public sealed interface ManagementArticle 
  extends Article permits AgileArticle{}

public final class AgileArticle 
  implements ManagementArticle{}

public non-sealed interface AbstractArticle 
  extends Article{}

public final class PoliticalArticle 
  implements AbstractArticle{}

Singura diferență față de clasele sealed este că o interfață nu poate fi definită final. Interfețele copil pot fi doar sealed sau non-sealed.