Chester 中的特質和介面

Chester提供了兩種不同的機制來定義抽象類型:特質(traits)和介面(interfaces)。雖然它們都用於定義其他類型可以實現的契約,但它們在子類型行為和預期用例方面有所不同。

特質:名義子類型

Chester中的特質使用名義子類型(nominal subtyping),這意味著類型的名稱在確定子類型關係時很重要。

以下是 Chester 中的特質定義範例:

trait Animal {
  def makeSound: String;
}

object Dog <: Animal {
  override def makeSound: String = "Woof!";
}

在此例中,Dog 通過使用 <: 操作符明確聲明為 Animal 的子類型。這種關係基於類型的名稱,而不僅僅是它們的結構。

介面:結構子類型

Chester中的介面使用結構子類型(structural subtyping),這意味著子類型關係是由類型的結構(方法和屬性)決定的,而不考慮它們的名稱。

以下是介面定義的範例:

interface Soundmaker {
  def makeSound: String;
}

object Cat {
  def makeSound: String = "Meow!";
}

// Cat is implicitly a Soundmaker because it has a matching structure
def soundmaker: Soundmaker = Cat;

在這個例子中,Cat 被視為 Soundmaker 的子類型,因為它有一個匹配的 makeSound 方法,即使它並沒有被明確聲明為這樣。

設計靈感

這種對抽象類型的雙重方法受到 Pony 程式語言的啟發,如以下文獻所述:

Steed, G., & Drossopoulou, S. (2016). A principled design of capabilities in Pony. URL: https://www.ponylang.io/media/papers/a_prinicipled_design_of_capabilities_in_pony.pdf

The Pony language uses a similar distinction between traits (which they call “interfaces”) for nominal subtyping and “structural types” for structural subtyping.

在特質和介面之間選擇

  • 當您想要創建命名的類型層次結構並控制哪些類型可以成為子類型時,請使用特質。
  • 當您想要定義任何類型都可以通過實現所需結構而隱式滿足的契約時,請使用介面。

這種設計給予Chester開發者靈活性,使他們能夠根據需要同時使用嚴格的類型層次結構和更靈活的鴨子類型風格編程。