前言
介面 (interface) 和特質 (trait) 都是受限制的多重繼承,是 Groovy 中為了補償單一繼承的不足所實作的語法特性。兩者的差別在於前者沒有實作而後者有。
介面 (Interface)
介面 (interface) 是只有方法 (method) 宣告但沒有 method 實作的類別,主要目的是在滿足子類別 (subtying) 的前提下避開多重繼承的問題。介面的虛擬碼如下:
interface Interface {
// Declare some methods with no implementations.
}
class Child extends Parent implements Interface {
// Implicitly inherit some fields from Parents.
// Declare some fields.
public Child(param_a, param_b, param_c) {
// Init fields.
}
// Implicitly inherit some methods from Parent.
// Child has to implement the methods in Interface.
// Other methods in Child.
}
extends
和 implements
都是繼承,但兩者的行為大不相同。extends
會繼承父類別 (parent class) 實際的屬性和行為,但只能繼承單一的父類別;implements
僅繼承介面的 methods 宣告,要自行實作介面的內容。和 extends
不同的點在於 implements
可同時繼承多個介面。在同一個類別中,可以同時使用兩種繼承的方式,因為 implements
本來就是一種受限制的多重繼承。
以下例子實做三個滿足同一個介面的類別:
interface Speak {
public String speak()
}
class Dog implements Speak {
public String speak() {
return "Wow wow"
}
}
class Duck implements Speak {
public String speak() {
return "Pack pack"
}
}
class Tiger implements Speak {
public String speak() {
return "Halum halum"
}
}
def animals = [new Dog(), new Duck(), new Tiger()]
animals.each { println it.speak() }
在本例中,由於三個物件繼承自同一個介面,可視為相同型別,故可以放在同一個陣列中。
Groovy 同時具有 interface
和 trait
兩種相似的語法機制,算是有點冗餘的設計。如果沒有要實作程式碼的話,最好還是使用 interface
,比較不會搞混。
特質 (Trait)
特質 (trait) 和介面 (interface) 算是有點重疊的特性,兩者都是做為受限制的多重繼承的語法特性,主要的差別在於 traits 可以加入實作。參考下例:
trait Greetable {
abstract String getName()
String greeting() {
"Hello ${name}"
}
}
class Person implements Greetable {
private String _name
public Person(String name) {
_name = name
}
public String getName() {
return _name
}
}
def p = new Person("Michelle")
assert p.greeting() == "Hello Michelle"
由於 trait 可以加入自己的屬性和方法,已經相當接近多重繼承,在撰寫 trait 要妥善安排程式碼的架構,以免寫出難以維護的程式碼。