Go面向對象編程

Go並非一個相似於Java、C++,或PHP這樣內置面向對象語法的操做的語言,在Go裏面名義上是沒有類(class)這個概念的,可是這並不表明Go不能面向對象,畢竟面向對象只是一種設計思想!bash

爲何Go並不原生支持面向對象呢?這是一個問題app

接下來,我會從面向對象的三大特性封裝、繼承、多態這個幾個方面來說講Go是怎麼實現的OOP的。函數

1.封裝

閒話少說,在Go裏面可使用結構體模擬類:ui

type Goods struct {
    name  string
    price int
}
複製代碼

在Go裏面有一個約定俗稱的規則,變量名、結構體名、結構體屬性成員名大寫表明是公開權限,能夠被其它包使用。相似於類的public屬性。若是小寫就相似於private屬性。spa

類裏面除了屬性以外,通常會有本身的方法,在Go裏面能夠這樣實現(這裏我採用的是Go modules結構):設計

package models

import "fmt"

type Goods struct {
    Name  string
    Price int
}

func (g *Goods) GetName() string {
    return g.Name
}

func (g *Goods) SetName(name string) {
    g.Name = name
}

func (*Goods) String() {
    fmt.Println("I am Goods")
}
複製代碼

其實就是在函數名前加一個類型聲明,若是你在方法裏面不須要使用類自己,則能夠省略參數標識。code

如何使用這個「類呢」?對象

package main

import (
    "demo/models"
    "fmt"
)

func main() {
    goods := models.Goods{
        "筆記本", 100,
    }
    
    fmt.Printf("Goods name is %s\n", goods.GetName())
    
    goods.SetName("小米筆記本")
    
    fmt.Printf("Goods name is %s\n", goods.GetName())
}
複製代碼

咱們能夠採用字面量賦值的方式初始化對象,雖然結構體並無構造函數這個東西,可是咱們能夠造個差很少的方式出來。繼承

新增這個方法:接口

func NewGoods(name string, price int) Goods {
    g := Goods{
        Name:  name,
        Price: price,
    }
    return g
}
複製代碼

而後咱們就能夠這樣使用:

var goods models.Goods
goods = models.NewGoods("筆記本", 1000)
複製代碼

其實區別卻是不大,封裝了一下,更加簡潔,雖然達不到構造函數自動調用的效果。

2.繼承

Go裏面並無extends這樣的語法,可是結構體的成員能夠是結構體,這其實是使用組合實現了繼承的效果。

package models

type Apple struct {
    Goods //繼承了Goods
    Color string
}

// 構造函數
func NewApple(name string, price int, color string) Apple {
    apple := Apple{
        Goods{name, price},
        color,
    }
    
    return apple
}
複製代碼

main.go:

package main

import (
    "demo/models"
    "fmt"
)

func main() {
    apple := models.NewApple("紅富士蘋果", 200, "red")
    fmt.Printf("Apple name is %s", apple.GetName())
}
複製代碼

Apple可使用Goods的方法和屬性,使用組合的好處就是不存在多繼承的限制,在不少面向對象的語言裏面,只能單繼承。

3.多態

雖然Go裏面也沒有implements這樣的關鍵字,可是在Go裏面可使用interface來實現多態效果,並且Go裏面的接口至關靈活。

定義接口:

package models

type Saleable interface {
    Sell()
}
複製代碼

實現接口(Apple):

func (Apple) Sell()  {
    fmt.Println("我實現了saleable接口")
}
複製代碼

使用:

func main() {
    apple := models.NewApple("紅富士蘋果", 200, "red")
    
    var i models.Saleable
    
    i = &apple
    
    i.Sell()
}
---結果---
我實現了saleable接口
複製代碼

劃重點,在GO裏面只要一個結構體(struct)定義了一個接口(interface)裏面的全部方法,就意味着這個這個struct實現了這個接口,這是隱式的。可見,在Go裏面接口仍是挺好用的。

相關文章
相關標籤/搜索