We should not allow bullDog or beagle to extend bigCat class since there are not cats, in the same way we should also not allow tiger and leopard to extend dog class since they are not dogs.Until java 14 there is no direct way to restrict one class from extending other.This means that the classes bullDog and beagle can get all the features of the class bigCat just by extending it and this is not desirable.
So we can implement the classes as shown in the figure by using some tricks.We can implement it by making the constructor of bigCat and dog as private.After that we can use nesting of classes to put the classes tiger and leopard inside the class bigCat and bullDog and beagle inside the class dog.BY doing so we make a very clever usage of visibility restrictions of private constructors and nested classes.
The actual implementation is shown below:-
package animal;
public class cat {
private cat() {}
.
.
.
.
public final class tiger extends cat {...
}
public final class leopard extends cat{...
}
}
public class dog {
private dog() {...
}
.
.
.
public final class bullDog extends dog {...
}
public final class beagle extends dog {...
}
}
This is not exactly what we wanted but it works the same way.
We can also restrict one class from extending the other by declaring it as final.In such a scenario a class will have zero subclasses so we cannot implement class inheritance which means we cannot reuse the code.
However, the purpose of a class inheritance is not always to reuse code. Sometimes, its purpose is to model the various possibilities that exist in a domain. When the class inheritance is used in this way, restricting the set of subclasses can streamline the modeling.So code reuse is not always a goal,But Java assumes that code reuse is always a goal.So until java 14 ,if one class is extended at all then it can be extended by any number of classes.This is where the concept of "Java sealed classes and interfaces" which is introduced as a preview feature in java SE 15 comes in. This feature help's us to restrict one class from extending the other.Java developers are familiar with the idea of restricting the set of subclasses because it often used in API design.
A sealed class or interface can be extended or implemented only by those classes and interfaces permitted to do so. A class is sealed by applying the keyword sealed to its declaration.After that if the class itself is extending some other class then it is written .Then after that the "permits" keyword is used and then all the classes which are allowed to extend the current class is mentioned.For example:-
public sealed class bigCat permits tiger,leopard {...}
public sealed class dog permits bullDog,beagle {...}
In the above example only the classes tiger and leopard are allowed to extend bigCat and the classes bullDog and beagle are allowed to extend dog.Note that the classes specified by permits must be located near the superclass: either in the same module or in the same package.
When the permitted subclasses are small in size and number, it may be convenient to declare them in the same source file as the sealed class. When they are declared in this way, the sealed class may omit the permits clause, and the Java compiler will infer the permitted subclasses from the declarations in the source file (which may be auxilliary or nested classes). For example, if the following code is found in bigCat.java, then the sealed class bigCat is inferred to have two permitted subclasses:
package animal;
sealed class bigCat {...}
... class tiger extends bigCat {...}
... class leopard extends bigCat {...}
A sealed class imposes three constraints on its permitted subclasses :
1.The sealed class and its permitted subclasses must belong to the same module, and, if declared in an unnamed module, the same package.
2.Every permitted subclass must directly extend the sealed class.
3.Every permitted subclass must choose a modifier to describe how it continues the sealing initiated by its superclass:
A permitted subclass may be declared final to prevent its part of the class hierarchy from being extended further.
A permitted subclass may be declared sealed to allow its part of the hierarchy to be extended further than envisaged by its sealed superclass, but in a restricted fashion.
A permitted subclass may be declared non-sealed so that its part of the hierarchy reverts to being open for extension by unknown subclasses.
One and only one of the modifiers final, sealed, and non-sealed must be used by each permitted subclass. It is not possible for a class to be both sealed and final or non-sealed and final or sealed and non-sealed.
Full Implementation:
package animal;
public sealed class cat permits tiger,leopard {...
}
public final class tiger extends cat {...
}
public final class leopard extends cat{...
}
public sealed class dog permits bullDog,beagle {...
}
public final class bullDog extends dog {...
}
public final class beagle extends dog {...
}
NOTE:-Permitted subclasses need not have the same accessibility as each other, or as the sealed class. In particular, a subclass may be less accessible than the sealed class.
Sealed interfaces are also implemented in the similar way as sealed classes i.e just use the keyword before the interface name and then give the list of class or interfaces which can implement it after the permitted keyword.
Nicely Done
ReplyDeleteNicely explained
ReplyDelete