首頁  >  文章  >  後端開發  >  golang中有沒有類

golang中有沒有類

青灯夜游
青灯夜游原創
2023-01-12 16:56:043904瀏覽

golang中沒有類別。 golang不是純粹物件導向程式語言,它沒有class(類別)的概念,也就沒有繼承的說法,但Go也可以模擬物件導向的程式設計方式。在Go中,可以將struct比喻為其它語言中的class;透過struct定義結構體,表徵一類對象,例「type person struct {...}」。

golang中有沒有類

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

物件導向三大特徵:封裝,繼承,多型。

Go不是一門純粹物件導向程式語言,它沒有class(類別)的概念,也就沒有繼承的說法。但Go也可以模擬物件導向的程式設計方式,也就是可以將struct比喻為它語言中的class。

物件

Go沒有class的概念,透過struct定義結構體,表徵一類物件。

type person struct {
	Age  int
	Name string
}

物件是狀態與行為的有機體。例如下面的java程式碼:

public class Person {

    int age;

    String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

不同於Java,Go的方法不需要跟類別的資料綁定在一個class的定義裡面,只需要定義在同一個套件內。這一點可能初學Go的同學,會覺得很奇怪。

type person struct {
	Age  int
	Name string
}

func (p *person) GetAge() int {
	return p.Age
}

func (p *person) SetAge(age int)  {
	p.Age = age
}

func (p *person) GetName() string {
	return p.Name
}

func (p *person) SetName(name string) {
	p.Name = name
}

建構子

Go沒有建構函數,物件的資料載體就是一個struct。 Java支援建構函數,建構函數名字就跟類別名字一樣,多個建構子透過函數重載實現。

而Go建構函式則透過工廠函數進行模擬。實例如下:

type person struct {
	Age  int
	Name string
}

/**
	构造函数1--通过名字初始化
 */
func newPersonByName(name string) *person {
	return &person{
		Name: name,
	}
}

/**
	构造函数2--通过年龄初始化
 */
func newPersonByAge(age int) *person {
	return &person{
		Age: age,
	}
}

要注意的是,person結構體的名稱首字母要小寫,避免外部直接越過模擬的建構子

##存取權限

Java有四種存取權限,如下所示:

java存取控制符# friendly##同一個類別yesyesyesyes同一個套件yesyesyesno#不同套件子類別yesyesnono不同套件非子類別yesnonono 
##public #protected

(default)

#private
 

 

 

 

 

Go則做了簡化,可見性的最小粒徑是包。也就是說,Go保留兩種,friendly和public。 Go的變數名稱如果首字母是小寫,則代表包內可見;如果首字母是大寫,則代表任何地方都可見。

封裝

封裝,把抽像出來的結構體跟操作結構體內部資料的函數綁定在一起。外部程式只能根據匯出的函數API(public方法)修改結構體的內部狀態。

封裝有兩個好處:

隱藏實作:我們只希望使用者直接使用API​​作業結構體內部狀態,而無需了解內部邏輯。就好像一座冰山,我們只看到它露出水面的那一部分。

保護資料:我們可以對資料的修改和存取施加安全措施,呼叫setter方法的時候,我們可以對參數進行校驗;呼叫getter方法,我們可以增加存取日誌等等。

一個簡單的bean定義如下所示:

type person struct {
	Age  int
	Name string
}

func NewPerson(age int, name string) *person{
	return &person{age, name}
}

func (p *person) SetAge(age int)  {
	p.Age = age
}

func (p *person) SetName(name string) {
	p.Name = name
}

func main() {
	p:= NewPerson(10, "Lily")
	p.SetName("Lucy")
	p.SetAge(18)
}
要注意的是,Go的方法是一種特殊的函數,只是編譯器的一種語法糖,編譯器瞧瞧幫我們把物件的引用當作函數的第一個參數。例如,下面的程式碼是等價的

func main() {
	p:= NewPerson(10, "Lily")

	p.SetName("Lily1")
	// 等价于下面的写法
	// p是一个引用,函数引用
	setNameFunc := (*person).SetName
	setNameFunc(p, "Lily2")
	fmt.Println(p.Name)
}

繼承

繼承,子類繼承父類,則獲得父類的特徵和行為。繼承的主要目的是為了重複使用程式碼。 Java實作程式碼重用的兩大利器,就是繼承和組合。

Go沒有class的概念,談不上繼承。但Go可以透過匿名組合來模擬繼承。

如下所示,Cat透過匿名聚合了Animal結構體,就自動獲得了Animal的move()和Shout()方法:

type Animal struct {
	Name string
}

func (Animal) move()  {
	fmt.Println("我会走")
}

func (Animal) shout()  {
	fmt.Println("我会叫")
}

type Cat struct {
	Animal // 匿名聚合
}

func main() {
	cat := &Cat{Animal{"猫"}}

	cat.move()
	cat.shout()
}

多態

多態,申明為基類的變量,可以在運行期指向不同的子類,並呼叫不同子類的方法。多態的目的是為了統一實現。

我們透過介面來實現多態。在java裡,我們透過interface來定義接口,透過implements實現接口。

interface Animal {

    void move();

    void shout();
}

class Dog implements Animal {

    @Override
    public void move() {
        System.out.println("我会走");
    }

    @Override
    public void shout() {
        System.out.println("我会叫");
    }
}
而Go則是透過

鴨子類型

推斷,只要某個物件長得想鴨子,叫起來像鴨子,那麼它就是鴨子。也就是說,Go的介面是比較隱匿的,只要某個物件實作來介面申明的所有方法,那麼就認為它屬於該介面。

type Animal interface {

	move()
	shout()
}

type Cat struct {
	Animal // 匿名聚合
}

func (Cat)move()  {
	fmt.Println("猫会走")
}

func (Cat)shout()  {
	fmt.Println("猫会叫")
}

type Dog struct {
	Animal  // 匿名聚合
}


func (Dog)move()  {
	fmt.Println("狗会走")
}

func (Dog)shout()  {
	fmt.Println("狗会叫")
}

func main() {
	cat := Cat{}
	dog := Dog{}
    // 申明接口数组
 	animals := []Animal{cat, dog}
	for _,ele := range animals {
        // 统一访问
		ele.move()
		ele.shout()
	}
}
【相關推薦:Go影片教學、

程式設計教學

以上是golang中有沒有類的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn