golang interface淺談

themoonstone發表於2017-03-30

golang 的介面設計是這門程式語言的兩大亮點之一,本文僅淺談 golang 介面和其它語言 (以 C++ 為例) 的區別。 引用《Go 語言程式設計》作者在書中的話,go 語言中的介面是 “非侵入式” 的,而其它語言中的介面是 “侵入式” 的。因此,需要對非侵入式和侵入式分別理解才能理解清楚 golang 介面的優點 首先 讓我們看看 C++ 中的介面: 在 C++ 中,介面的實現必須要通過繼承

interface IFoo{
    void Bar();
}

class Foo: public IFoo
{}

IFoo *Foo=new IFoo;

在此類語言中 即使另外有一個介面 IFoo2 實現了與 IFoo 完全一樣的介面方法,甚至名字相同只不過位於不同的名字空間下,編譯器也會認為上面的類 Foo 只實現了 IFoo 的介面,而沒有實現 IFoo2 的介面 此類介面稱為侵入式介面。“侵入式” 的主要表現是實現類必須明確表示自己實現了某個介面。在 C++ 裡面表示為需要繼承。 舉一個具體的例項:

#include <iostream>
using namespace std;

class Person
{
    public:
    Person():m_strName("###"){};
    virtual void SetName(const string name)=0;
    private:
    string m_strName;
};

class Person2
{
    public:
    Person2():m_strName("###"){};
    virtual void SetName(const string name)=0;
    private:
    string m_strName;
};

class Student:public Person
{
    public:
    Student():m_strName("***"){};
    void SetName(const string name);
    private:
    string m_strName;
};

void Student::SetName(const string name){
    std::cout << m_strName << std::endl;
    m_strName=name;
    std::cout << m_strName << std::endl;
}

int main() {
    Student s;
    Person *p;
    p=&s;
    Person2 *p2;
    p2=&s;
    return 0;
}

在這裡 因為 Student 沒有宣告繼承 Person2 所以 針對 p2=$s;這段程式碼 會出現:“cannot convert Struden* to Person2 in assignment” 這樣的錯誤。 而在 GO 語言中,一個類只要實現了該介面所有的函式,就代表這個類實現了該介面

type file struct{}
func(f *File) Read(buf []byte)(n int, err error)
func(f *File) Write(buf []byte)(n int, err error)
func(f *File) Seek(off int64, err eror)(pos int, err error)
func(f *File) Close() err error

type IFile interface{
    Read(buf []byte)(n int, err error)
    Write(buf []byte)(n int, err error)
    Seek(off int64, err eror)(pos int, err error)
    Close() err error
}

type IReader interface
{
Read(buf []byte)(n int, err error)
}
type IWriter interface
{
 Write(buf []byte)(n int, err error)
}
type ICloser interface
{
 Close() err error
}

儘管 file 類並沒有從這些介面繼承,甚至可以不知道這些介面的存在,但是 file 實現了這些介面的所有方法,就可以說 file 類實現了這些介面,可以進行賦值 其實我們可以用一個通俗的例子來進行一下說明: 對於侵入式介面,假設你在參加高考,但不是全國統考,而是高校自主命題,此時有 X 大學和 Y 大學兩所學校,他們的考試題目是完全相同的,錄取分數也是完全相同的,但就算你參加了 X 大學的考試,達到了 X 大學的分數線,你也不能申請就讀 Y 大學,要想申請 Y 大學,你必須再次參加 Y 大學的考試並達到 Y 大學的分數線,這裡的參加考試並達到分數線就相當於 C++ 中的繼承,如果沒有宣告繼承,就不能說明實現了某個介面 而對於非侵入式介面,同樣是高考,但這次是全國統考,你考過了分數線,這個時候 你既能申請 X 大學,又能申請 Y 大學,因為你達到了這兩所大學所要求的統一分數,相當於你實現了 X 和 Y 兩個介面裡的所有方法,所以既能呼叫 X 又能呼叫 Y 綜上,侵入式介面和非侵入式介面區別的關鍵在於是否需要明確宣告你的類實現了某個介面。 以上僅代表個人理解,對於不對的或者不恰當的地方,歡迎批評和指正。

更多原創文章乾貨分享,請關注公眾號
  • golang interface淺談
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章