The course is part of this learning path
In this course, we will learn the concepts of microservice and spring framework with a focus on inheritance.
- Inheritance in Java
- Beginner Java developers
- Java developers interested in learning how to Build and Deploy RESTful Web Services
- Java Developers who want to develop web applications using the Spring framework
- Java Developers who want to develop web applications with microservices
- Java Developers who wish to develop Spring Boot Microservices with Spring Cloud
- Basic Java knowledge
Hello, there. In this video, we will talk about sealed classes. Sealed classes are a concept that came into our lives with Java 15. Sealed classes, previewed in Java 15 and Java 16, are now fully available with Java 17. This feature is about enabling more fine-grained inheritance control in Java. Sealing allows classes and interfaces to define their permitted subtypes. In other words, a class or an interface can now define which class can implement or extend it. It's a useful feature for domain modeling and increasing the security of libraries. One of the primary purposes of inheritance is code reuse. When you want to create a new class and there's already a class that includes some of the code that you want, you can derive your new class from the existing class. In doing this, you can reuse the fields and methods of the existing class without having to write and debug them yourself. However, what if you want to model the various possibilities that exist in a domain by
defining its entities and determining how these entities should relate to each other?
For example, you're working on a graphics library. You want to determine how your library should handle common geometric primitives like circles and squares. You've created Shape class that these geometric primitives can extend. However, you're not interested in allowing any arbitrary class to extend Shape. You don't want clients of your library declaring any further primitives. By sealing a class, you can specify which classes are permitted to extend it and prevent any other arbitrary class from doing so. Now, let's look at defining the sealed classes. To seal a class, add the sealed modifier to its declaration. Then, after any extends and implements clauses, add the permits clause. This clause specifies the classes that may extend the sealed class. If we examine the example on the slide, the declaration of Shape specifies three permitted subclasses, Circle, Triangle, and Rectangle.
In this case, only the Circle, Triangle, and Rectangle classes can inherit from the Shape class. Other than these three classes, other classes cannot inherit from the Shape class. Also note that subclasses that inherit from any sealed class must be final, sealed, or non-sealed. Otherwise, you will get a compiler error. If you no longer want a subclass that inherits from a sealed class to be extended by other classes, you can define the subclass as final, or if you want it to be inherited by certain classes, then you should also define the subclass as sealed. If you want a subclass that inherits from a sealed class to now be extended by other classes, then you can define that subclass as non-sealed. Yes, friends, we talked theoretically about the sealed class and I think you understand what the sealed classes are used for. So, now let's move on to the Eclipse and get some practice. First, let's create a new package.
In the object-oriented project, I right-click on the source folder. I choose 'New class'. Let the package name be sealedclasses. Let the class name be Shape. You can create this class as sealed by selecting the sealed option here, but I want to create it myself. Therefore, I will not make any changes here. I create this class by clicking the 'Finish' button. The Shape class will be our sealed superclass. But before I qualify this class as sealed, I want to create the other classes in order. I right-click on the sealed classes package and select 'New class'. Let this class be called Rectangle. I create this class by clicking the 'Finish' button. This class will be one of the classes that extend the sealed Shape class. Now, let's create the second subclass. I right-click on the sealedclasses package and select 'New class'.
Let this class be called Circle. I create this class by clicking the 'Finish' button. Now, let's create the third subclass. Let this class be called Triangle. I create this class by clicking the 'Finish' button. So, we created the classes, now let's define the Shape class as a sealed class. To define a class as a sealed class, simply use the keyword sealed before the class statement. So, the Shape class is now a sealed class. But if you pay attention, we get a compiler error because if you make a class a sealed class, you must also define the classes that will extend that class with the permits keyword. That's why I write the keyword permits right after the class name. Now, let's determine the classes that will inherit from this class. In the first place, only the rectangle and circle classes inherit from the Shape class. That's why I write the Rectangle and Circle classes after the permits keyword.
We separate these classes with a comma. So, we sealed the Shape class to extend only the Rectangle and Circle classes, now let's save our code. Notice that the words Rectangle and Circle are underlined, so we are currently getting a compiler error. This is because these classes must extend the Shape class. So, let's open the Rectangle class. In order for this class to extend from the Shape class, I write extends Shape right after the class name. And I am saving the code. Notice that the compiler error in the Rectangle class and the Shape class has been removed? But this time we start getting an error in the Rectangle class. This is because subclasses that extend sealed classes must be final, sealed, or non-sealed, so the Rectangle class must be final, sealed, or non-sealed. If you position your mouse over the word Rectangle, you will see the following message in the dialog that opens.
The class Rectangle with a sealed direct superclass or a sealed direct superinterface Shape should be declared either final, sealed, or non-sealed. What did I say? So, we should use one of these three keywords. What do you think? Which keyword should we use? As I mentioned at the beginning of the lesson, if you don't want this class to be inherited by other classes, use the "final" keyword. If you want it to be inherited only by certain classes, use the "sealed" keyword. If you want it to be inherited by all other classes, use the non-sealed keyword. I will use the keyword sealed for the Rectangle class. I write sealed just before the class name. Of course, in this case, we must specify the classes that will extend this class with the "permits" keyword. Let's create another class for this. I right-click on the sealedclasses package and select 'New class'. Let the name of this class be Square. I create this class by clicking the 'Finish' button. Now, let's go back to the Rectangle class.
Here, I will write permit Square right after the class name. All right, let's save our code. Of course, we are getting error in the Square class because the Square class must also be final, sealed, or non-sealed and it should extend the Rectangle class. I don't want this class to be inherited by other classes anymore. So, I'm going to let the square class be final. And after the class name, I write extends Rectangle. Okay, everyone, let's save our codes. So, the Shape, Rectangle, and Square classes are ready. Now let's fix the compiler error in the Circle class. So, the Circle class should extend the Shape class. I write extends Shape right after the class name. And I'm saving the code. If you notice, the compiler error persists because the Circle class also needs to be, you said it, final, sealed, or non-sealed. I want this class to be non-sealed. Now let's create a different class and let this class be a subclass of the Circle class. I right-click on the sealedclasses package and select 'New class'. Let the name of this class be Oval, and I click the 'Finish' button. This class will extend the Circle class, so after the class name I write extends Circle.
And I save the code and I will save the Circle class again. Okay, now let's try to extend the Triangle class to the Shape class. I open the Triangle class. I will write extends Shape right after the class name. Notice that the Shape word is underlined by the compiler, so we get a compilation error. This is because the Shape class is a sealed class and only the Rectangle and Circle classes are allowed for subclassing. If you position your mouse over the word Shape, you will see this message. The type Triangle extending a sealed class Shape should be a permitted subtype of Shape. As you can see, while we can inherit the classes we want with sealed classes, we cannot inherit the classes we do not want. I think you understand better now. Let's give inheritance permission to the Triangle class if you want. Let's go back to the Shape class. I'm also adding the Triangle class here.
Okay, let's save our code. Now let's go back to the Triangle class. As you see, the warning under the Shape class has been removed, but we are getting one more error, because this class must be final, sealed, or non-sealed. Since we will not inherit any class from this class, we can set it as final. So, we learned what sealed classes are used for and how they are used. To sum it up, we can customize the inheritance process thanks to sealed classes. For this, we can define the superclass with a sealed keyword and specify the classes to inherit with the permits keyword. Classes that inherit from a sealed class must also be defined as final, sealed, or non-sealed. All right, my friends, let's take a short break here and I'll see you in the next lesson.
OAK Academy is made up of tech experts who have been in the sector for years and years and are deeply rooted in the tech world. They specialize in critical areas like cybersecurity, coding, IT, game development, app monetization, and mobile development.