Java

Java Sealed Classes

葉宗原 2021/06/11 17:00:00
129

Introduction

Java 16推出也兩個月了,照預定進度,(2021年) 9月即將推出Java 17,同時也是LTS。

目前的LTS分別有

  • Java 8(最後延伸支援日期為2030 年 12 月)
  • Java 11(最後延伸支援日期為2026 年 9 月)

Java 8 目前處於屹立不搖的地位,其中一種原因就是因為最後延伸支援日期。雖然尚未公布,不過可以期待Java 17的最後延伸支援日期,除了必然會晚於Java 11外,也極有可能晚於萬年不敗的Java 8

Sealed Classes 在 Java 15 版本開始發布 Preview(JEP 360),並且在 Java 16 版本發布Second Preview(JEP 397);雖然 Java 17 尚未推出,但也被列為擬定目標(JEP 409)。我們可以提前來看看這個新語法。

Enable preview features

[Eclipse設定]

Eclipse Version: 2021-03 (4.19.0)

目前僅支援到 Java 15,必須先利用 patch方式更新來支援 Java 16

讓我們開啟Eclipse Marketplace,搜尋 'Java 16' 並安裝插件

接著enable preview features : 直接在Project->Properties中設定

Let's try

開始建立第一個Sealed Classes

public abstract sealed class Animal permits Dog,Cat,Bird {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Animal [name=" + name + "]";
	}
}

這裡出現了兩個新的關鍵字

  • sealed:宣告為密封類,僅允許特定類繼承(extend)
  • permits:宣告上述特定類

運用新的特性,上帝創造了嚴謹的動物,也就是狗、貓、以及鳥。世界上再也沒有其他動物。

當繼承Sealed Classes,必須要加入以下關鍵字的其一

  • final:老朋友,不允許繼承
  • sealed:繼承類同時為密封類,僅允許特定類繼承
  • non-sealed:繼承類為非密封類,允許任意類繼承

詳見以下範例

public final class Dog extends Animal {
	public Dog() {
		this.name = "Dog";
	}
}

final 是既有關鍵字,可以設計封閉的繼承樹。

狗,忠誠的狗,老狗,變不出新把戲,就只是隻狗。

public sealed class Cat extends Animal permits PersianCat,AmericanShorthair,Chinchilla {
	public Cat() {
		this.name = "Cat";
	}
}

public final class PersianCat extends Cat {
	public PersianCat() {
		this.name = "Persian cat";
	}
}

// skip

使用 sealed 則可以設計更長的繼承樹,同時更下層的類也需要加入關鍵字final/sealed/non-sealed

任性的貓告訴上帝他要繁衍的子嗣:波斯貓、美短、金吉拉。他們都是貓。

public non-sealed class Bird extends Animal {
	public Bird() {
		this.name = "Bird";
	}
}

public class Bat extends Bird{
	public Bat() {
		this.name = "Bat";
	}
}

使用 non-sealed 則可以解放繼承限制,也就是開放任意類繼承。

鳥類太廣泛了,會飛的蝙蝠也常常被誤認為鳥類?

Summary

在不久的將來,Java 17 上線後,你的商業邏輯也有一些想要限制繼承的需求嗎?一起來更新Java版本,使用新特性吧。

葉宗原