[Groovy] 程式設計教學:介面 (Interface) 和特質 (Trait)

【分享本文】
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
【贊助商連結】

    介面 (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.
    }

    extendsimplements 都是繼承,但兩者的行為大不相同。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 同時具有 interfacetrait 兩種相似的語法機制,算是有點冗餘的設計。如果沒有要實作程式碼的話,最好還是使用 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("Michael")
    assert p.greeting() == "Hello Michael"

    由於 trait 可以加入自己的屬性和方法,已經相當接近多重繼承,在撰寫 trait 要妥善安排程式碼的架構,以免寫出難以維護的程式碼。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
    【支持站長】
    Buy me a coffeeBuy me a coffee
    【贊助商連結】
    標籤: GROOVY, JAVA
    【分類瀏覽】