golang面向對象編程思想


抽象介紹:

  在定義一個結構體的時候,實際上就是把一類事物的共有屬性(字段)和行為(方法) 提取出來,形成一個物理模型(模板),這種研究問題的方法稱為抽象。

封裝:

  把抽象出的字段和對字段的操作封裝在一起,數據被保護在內部,程序的其它包只有通過被授權的操作(方法),才能對字段進行操作。

  1)將結構體、字段(屬性)的首字母小寫

  2)給結構體所在包提供一個工廠模式的函數,首字母大寫,類似一個構造函數

  3)提供一個首字母大寫的Set方法(類似其它語言的public),用於對屬性判斷並賦值

 model.go

package model

import (
    "fmt"
)

type account struct {
    username string
    password string
    balance float64
}

func NewAccount() *account {
    return &account{}
}

// 設置賬號
func (user *account) SetUsername(username string) {
    if len(username) < 6 && len(username) > 10 {
        fmt.Println("賬號長度必須是6到10位")
        return
    }
    user.username = username
}

func (user *account) GetUsername() string {
    return user.username
}

// 設置密碼
func (user *account) SetPassword(password string) {
    if len(password) != 6 {
        fmt.Println("密碼必須是6位")
        return
    }
    user.password = password
}

func (user *account) GetPassword() string {
    return user.password
}

// 設置余額
func (user *account) SetBalance(balance float64) {
    if balance < 20 {
        fmt.Println("余額必須大於20")
        return
    }
    user.balance = balance
}

func (user *account) GetBalance() float64 {
    return user.balance
}

main.go

package main

import (
    "fmt"
    "model"
)

func main() {
    user := model.NewAccount()
    user.SetUsername("admin123")
    user.SetPassword("123456")
    user.SetBalance(20)
    fmt.Println(user.GetUsername(), user.GetPassword(), user.GetBalance())
}

 

繼承:

  在golang中,如果一個struct嵌套了另一個匿名函數體,那么這個結構體可以直接訪問匿名結構體的字段和方法,從而實現了繼承特性。

  1)代碼的復用性提高了

  2)代碼擴展性和維護性提高了

  深入討論:

    1)結構體可以使用嵌套匿名結構體所有的字段和方法,即:首字母大小寫的字段、方法,都可以使用;

    2)匿名結構體字段訪問可以簡化:b.A.hobby()  ==> b.hobby();

    3)當結構體和匿名結構體有相同的字段或者方法時,編譯器采用就近訪問原則訪問,如希望訪問匿名結構體和字段和方法,可以通過匿名結構體名來區分;

    4)結構體嵌入兩個以上匿名結構體,如兩個匿名結構體有相同的字段和方法(同時結構體本身沒有同名的字段和方法),在訪問時,就必須明確指定匿名結構體名字,否則編譯報錯;

    5)如果一個struct嵌套了一個有名結構體,這種模式就是組合,如果是組合關系,那么在訪問組合的結構體的字段或方法時,必須帶上結構體的名字;

    6)嵌套匿名函數結構體后,也可以在創建結構體變量時(實例),直接指定各個匿名結構體字段的值;

 

接口:

  interface類型可以定義一組方法,但是這些不需要實現。並且interface不能包含任何變量。到某個自定義類型要使用的時候,在根據具體情況把這些方法寫出來。

  語法:

    type 接口名 interface {

      method1(參數列表) 返回值列表

      method2(參數列表) 返回值列表  

    }

  注意事項:

    1)接口本身不能創建實例,但是可以指向一個實現了該接口的自定義類型的變量(實例);

    2)接口中所有的方法都沒有方法體,即都是沒有實現的方法;

    3)在Golang中,一個自定義類型需要將某個接口的所有方法都實現,我們說這個自定義類型實現了該接口;

    4)只要是自定義數據類型,就可以實現接口,不僅僅是結構體類型;

    5)一個自定義類型可以實現多個接口;

    6)Golang接口中不能有任何變量

    7)一個接口(比如A接口)可以繼承多個別的接口(比如B,C接口),這時如果要實現A接口,也必須將B,C接口的方法全部實現;

    8)interface類型默認是一個指針(引用類型),如果沒有對interface初始化就使用,那么會輸出nil;

    9)空接口interface{}沒有任何方法,所以所有類型都實現了空接口,即我們可以把任何一個變量賦給空接口。

接口與繼承:

  繼承的價值主要在於:解決代碼的復用性和可維護性。

  接口的價值主要在於:設計,設計好各種規范(方法),讓其它自定義類型方法實現這些方法。

  接口比繼承更加靈活,繼承是滿足 is - a 的關系,而接口只需要滿足 like - a 的關系。

  接口在一定程度上實現代碼解耦。

多態:

  變量(實例)具有多種形態,面向對象的第三大特征,通過接口實現,可以按照統一的接口來調用不同的實現。這時接口變量就呈現不同的形態。

類型斷言:

  接口是一般類型,不知道具體類型,如果要轉成具體類型,就需要使用類型斷言。

    var t float32
    var x interface{}
    x = t
    y := x.(float32)
    print(y)

  如果在進行斷言時,帶上檢測機制,如果成功就ok,否則也不要報panic

    var t float32 = 1.1
    var x interface{}
    x = t
    if y, ok := x.(float32); ok {
        fmt.Println("convert success")
        fmt.Println("y 的類型是 %T 值是 %V", y, y)
    }else {
        fmt.Println("convert fail")
    }
    fmt.Println("繼續執行...")


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM