sealed 類別
June 6, 2022若你想設計另一個 RPG 程式庫,可以讓其他人拿來進一步設計遊戲,然而你想限定角色只有騎兵、戰士、魔導士、弓兵四種形態,在你定義了 Role
類別,讓 Knight
、Warrior
、Mage
、Archer
繼承 Role
之後,就面對了一個問題,該怎麼阻止其他人繼承 Role
呢?
sealed 與 permits
有時候要解決的問題領域中,某些模型的型態架構是已知的,你想控制型態的邊界,像是控制 Role
只能有方才四個子類別,在 Java 17 之前,沒有適當的方式可以達成這類需求,然而 Java 17 以後的 sealed
關鍵字,可以達到需求。例如:
public abstract sealed class Role
permits Knight, Warrior, Mage, Archer {}
final class Knight extends Role {}
final class Warrior extends Role {}
final class Mage extends Role {}
final class Archer extends Role {}
可以使用 sealed
關鍵字修飾的類別必須是抽象類別,permits
列出了允許的子類別,子類別必須在同一套件中定義,並且必須使用final
、non-sealed
、或 sealed
修飾,以上的程式片段使用了 final
,這表示其他人除了不能繼承 Role
以外,也不能建立Knight
、Warrior
、Mage
、Archer
的子類別。
non-sealed 或 final
如果使用 non-sealed
修飾,例如:
public abstract sealed class Role
permits Knight, Warrior, Mage, Archer {}
non-sealed class Knight extends Role {}
non-sealed class Warrior extends Role {}
non-sealed class Mage extends Role {}
non-sealed class Archer extends Role {}
這就表示其他人不能繼承 Role
,然而可以任意地建立 Knight
、Warrior
、Mage
、Archer
的子類別,也許目的是可以讓其他人,可以隨意定義騎兵、戰士、魔導士、弓兵進化後的延伸職業,例如騎兵可以進化為飛龍騎兵之類。
如果你也想進一步掌握騎兵、戰士、魔導士、弓兵進化後的延伸職業,像是騎兵進化後,只有飛龍騎兵、陸戰騎兵兩種,可以使用 sealed
修飾,並使用 permits
列出了允許的子類別。
sealed class Knight extends Role permits DragonKnight, MarineKnight {}
final class DragonKnight extends Knight {}
final class MarineKnight extends Knight {}
後續會談到介面,sealed
也可以用來修飾介面,這表示你很清楚介面會有幾種實作品或子介面,不允許其他人實作該介面或增加直接的子介面,實作類別必須在同一套件中定義,並且必須使用 final
、non-sealed
、或 sealed
修飾,子介面必須在同一套件中定義,並且必須使用 non-sealed
、或 sealed
修飾,這些等之後聊完介面再來說明。