Trong Java, để ngăn chặn việc kế thừa của một class nào đó, chúng ta sẽ sử dụng từ khoá final để khai báo cho class đó. Ví dụ như sau:
1 2 3 4 5 6 7 8 9 10 11 |
package com.huongdanjava.javaexample; public final class JavaExample { public static void main(String[] args) { } class Test extends JavaExample { } } |
Class Test sẽ không thể kế thừa class JavaExample vì class JavaExample này được khai báo với final:
Một nhu cầu đặt ra trong một số trường hợp là chúng ta cần chỉ định class nào được phép kế thừa từ class cha, class nào không. Chúng ta không muốn ngăn chặn việc kế thừa từ tất cả các class, vì có những trường hợp, chúng ta muốn một số class trong thư viện của mình được kế thừa từ class cha đó, không cho phép kế thừa từ những class khác.
Ví dụ như:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.javaexample; public class JavaExample { public static void main(String[] args) { } class Test1 extends JavaExample { } class Test2 extends JavaExample { } } |
Trong ví dụ này, mình muốn class Test1 và Test2 được kế thừa từ class JavaExample nhưng không muốn các class khác được kế thừa từ class JavaExample này. Mình không thể khai báo class JavaExample này với từ khoá final được. Và đó là lý do sealed class được giới thiệu trong Java.
Sealed class sẽ giúp chúng ta restrict việc kế thừa của một class nào đó. Chúng ta có thể control class nào được phép kế thừa từ class cha.
Để hiện thực sealed class, chúng ta sẽ sử dụng cặp từ khoá sealed và permits để khai báo cho class mà chúng ta muốn seal.
Trong ví dụ trên, mình sẽ khai báo như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.javaexample; public sealed class JavaExample permits JavaExample.Test1, JavaExample.Test2 { public static void main(String[] args) { } final class Test1 extends JavaExample { } final class Test2 extends JavaExample { } } |
Từ khoá sealed được khai báo sau access modifier của class và từ khoá permits sẽ được khai báo cùng với danh sách class con mà chúng ta cho phép chúng được kế thừa từ class này. Các bạn cũng để ý rằng, chúng ta cũng cần phải khai báo các class con là final để không class nào được kế thừa từ các class con này nữa.
Nếu các bạn có nhu cầu cho phép class Test1 được kế thừa từ những class khác tiếp thì hãy khai báo class Test1 này với từ khoá non-sealed. Khi đó class Test1 có thể được kế thừa mà không có bất kỳ giới hạn nào, ví dụ như:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.huongdanjava.javaexample; public sealed class JavaExample permits JavaExample.Test1, JavaExample.Test2 { public static void main(String[] args) { } non-sealed class Test1 extends JavaExample { } class Test3 extends Test1 { } final class Test2 extends JavaExample { } } |
Chúng ta cũng có thể tiếp tục restrict kế thừa cho class Test2 như class JavaExample bằng cách khai báo từ khoá sealed và permits:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.huongdanjava.javaexample; public sealed class JavaExample permits JavaExample.Test1, JavaExample.Test2 { public static void main(String[] args) { } non-sealed class Test1 extends JavaExample { } class Test3 extends Test1 { } sealed class Test2 extends JavaExample permits Test4 { } final class Test4 extends Test2 { } } |
Có một số điểm các bạn cần biết thêm là:
– Nếu class con nằm trong cùng class file với class cha thì các bạn có thể bỏ qua từ khoá permits. Ví dụ như trong ví dụ trên, mình có thể bỏ phần khai báo permits Test4 trong định nghĩa của class Test2 đi mà không bị lỗi gì:
– Local class (những class định nghĩa bên trong method) có thể kế thừa từ non-sealed class:
nhưng không thể kế thừa từ sealed class.