天天看點

Golang 用組合實作繼承

go語言既不支援類和對象,也不支援繼承。但是go提供了結構和方法。。

golang中沒有繼承的概念,但是可以使用組合結構和方法來實作類似c++等進階的繼承

#include <iostream>
using namespace std;

class Person {
public:
    void Say();
};
void Person::Say() {
    cout << "I'm a person." << endl;
}

// 繼承
class Student : public Person {
};

int main() {
    Student s;
    s.Say();
    return 0;
}
           

golang實作類似功能

package main

type Person struct {
}
func (p *Person) Say() {
    println("I'm a person.")
}

// 組合
type Student struct {
    Person
}

func main() {
    var s Student
    s.Say()
}
           

這兩個程式運作之後結果都是: 

I'm a person.

Go可以通過組合另一個類型來"繼承"它的所有行為,十分直覺。。。

但是c++和go的這2段代碼表達的意義還是有差别的:

c++類繼承表示Person類是Student類的父類,具有一種層次關系

Go的組合則表示Student 是個Person,是以Student包含了Person的所有行為,Person能幹的事兒,Student肯定也能幹,Student骨子裡還是一個Person。。。

例子2:

package main 
import "fmt"

type Base struct {
	Name string
}

func (b *Base) SetName(name string) {
	b.Name = name
}

func (b *Base) GetName() string {
	return b.Name
}

// 組合,實作繼承
type Child struct {
	base Base  // 這裡儲存的是Base類型
}

// 重寫GetName方法
func (c *Child) GetName() string {
	c.base.SetName("modify...")
	return c.base.GetName()
}

// 實作繼承,但需要外部提供一個Base的執行個體
type Child2 struct {
	base *Base  // 這裡是指針
}

func (c *Child2) GetName() string {
	c.base.SetName("canuser?")
	return c.base.GetName()
}

func main() {
	c := new(Child)
	c.base.SetName("world")
	fmt.Println(c.GetName())

	c2 := new(Child2)
	c2.base = new(Base)  // 因為Child2裡面的Base是指針類型,是以必須提供一個Base的執行個體
	fmt.Println(c2.GetName())
}