密封類別是先前在 JDK 15 中引入並在 JDK 17 中正式引入的功能。 密封類別 是一個不能由未明確允許的類別(在類別聲明中)擴展,因此子類別的數量是有限的並且可以提前知道。
它們的目的是允許更精確地控制繼承層次結構,並促進所有可能的子類別已知的域的建模,並提高程式碼的安全性和可維護性。
密封類和最終類型的類之間的區別在於,後者不能被任何類擴展,而密封類可以擴展有限數量的類課程。
假設我們有兩個類,一個 Shape 類和一個 Circle 類,它們都是普通類,所以 Shape 可以被任何類擴展。
public class Shape { // ... } public class Circle extends Shape { // ... }
如果我們在Shape類別中使用final關鍵字,那麼它就不能被任何類別擴充。
public final class Shape { // ... } public class Circle extends Shape { // Error // ... }
現在,如果我們希望 Shape 類別僅由某些類別(例如 Circle 和 Square)擴展,那麼我們可以將其宣告為 密封類別。
public sealed class Shape permits Circle, Square { // ... }
分析前面的聲明,我們發現需要在單字class之前放置sealed,以表明它是一個密封類別。然後,使用「permits」一詞,後面跟著可以擴展目前類別的類別列表,在上面的範例中,只有 Circle 和 Square 類別可以擴展 Shape 類別。
如果您使用抽象類型的類,即無法實例化但可以由其他類別擴展的類,也會發生同樣的情況。
public sealed abstract class Shape permits Circle, Square { // ... }
這個概念也可以應用在介面上。
public sealed interface Shape permits Circle, Square { // ... }
注意:允許的子類別必須與sealed類別位於同一模組或套件中,否則將顯示錯誤訊息。
一旦將類別宣告為seal 並指定了允許的類,當使用允許的類別擴展Shape 類別(透過放置extends Shape)時,IDE 將顯示類似於此的錯誤訊息Modifier 'sealed' ,'未密封'或'最終'預期,這是什麼意思? .
必須考慮到每個允許的類別(子類別)都必須使用以下關鍵字之一進行聲明:
為了將上述內容付諸實踐,讓我們使用 Shape 類別以及 Circle、Square 和 Triangle 類別來看看如何根據上面提到的內容來聲明允許的類別。
public class Shape { // ... } public class Circle extends Shape { // ... }
如果我們希望 Circle 類別是最終類型並且因此不能擴展,那麼它必須聲明如下:
public final class Shape { // ... } public class Circle extends Shape { // Error // ... }
這可以防止 Circle 類別被任何其他類別擴展。
如果我們希望 Square 類別是密封類型並且允許子類別可以擴展它,那麼它必須聲明如下:
public sealed class Shape permits Circle, Square { // ... }
對於此範例,每個允許的類別(SquareChild1 和 SquareChild2)都聲明為 Final 類型,以便它們不能由任何其他類別擴展。
public sealed abstract class Shape permits Circle, Square { // ... }
如果您希望這些類能夠擴展更多的類,那麼應該將它們聲明為密封的,或者它們可以由任何非密封的類擴展。
對於 Triangle 類,當它被聲明為非密封時,它允許任何其他類擴展該類,而無需指定允許的類。
public sealed interface Shape permits Circle, Square { // ... }
例如,如果您建立擴展 Triangle 的 TriangleChild 類,則不會顯示錯誤訊息。
public sealed class Shape permits Circle, Square, Triangle { // ... }
此時,重要的是要考慮到,如果您將一個類別聲明為非密封類,那麼您會以某種方式「破壞」 密封類 的目的,因為它允許此類由任何其他類別擴展,並且允許的子類別數量不受限制。
就其本身而言,記錄不能是密封類型,因為它已經是最終類型並且不能由任何其他類別擴展。但是您可以做的是在密封類型的 interface 中聲明一個 record (考慮到記錄不能擴展類,只能實現介面)。例如,如果您有一個名為 Rectangle 的記錄和一個 seal 類型的 Shape 接口,您可以在 Shape 接口中聲明 Rectangle ,這樣 Rectangle 就能夠實現 Shape 接口以及該接口包含的所有方法。
public class Shape { // ... } public class Circle extends Shape { // ... }
如果宣告為密封的類別具有內部類別(巢狀或內部類別),則假定這些類別屬於主類,因此無需將它們聲明為允許的。例如,如果您將 Animal 類別宣告為 seal,同時將 Dog 和 Cat 作為內部類,則這些類別不需要宣告為 allowed,但它們必須擴展主類別並為最終類型,密封或非密封。
public final class Shape { // ... } public class Circle extends Shape { // Error // ... }
密封類別是一種將類別層次結構限制為有限數量的允許子類別的方法,儘管我們已經看到,如果一個類別被聲明為非密封,那麼目的就有點丟失了,或透過聲明一個作為密封子類,您可以進一步擴展此層次結構。
需要考慮的是,在聲明一個類別為sealed時,這只指誰可以擴展它,而不會限制主類別實例的創建,也不會修改該類別的語義,即它不會修改類別的內在行為。
以上是Java 密封類的詳細內容。更多資訊請關注PHP中文網其他相關文章!