Go 面向對象編程

 

 

Go 並非徹底面向對象的編程語言。Go 官網的 FAQ 回答了 Go 是不是面嚮對象語言,摘錄以下。程序員

能夠說是,也能夠說不是。雖然 Go 有類型和方法,支持面向對象的編程風格,但卻沒有類型的層次結構。Go 中的「接口」概念提供了一種不一樣的方法,咱們認爲它易於使用,也更爲廣泛。Go 也能夠將結構體嵌套使用,這與子類化(Subclassing)相似,但並不徹底相同。此外,Go 提供的特性比 C++ 或 Java 更爲通用:子類能夠由任何類型的數據來定義,甚至是內建類型(如簡單的「未裝箱的」整型)。這在結構體(類)中沒有受到限制。golang

 

結構體替代類

Go 不支持類,而是提供告終構體。結構體中能夠添加屬性和方法。這樣能夠將數據和操做數據的方法綁定在一塊兒,實現與類類似的效果。web

文件結構:編程

workspacepath -> oop -> employee -> employee.go   編程語言

workspacepath -> oop -> main.go函數

//employee.go文件
package employee import ( "fmt" ) type Employee struct { FirstName string LastName string TotalLeaves int LeavesTaken int } func (e Employee) LeavesRemaining() { fmt.Printf("%s %s has %d leaves remaining", e.FirstName, e.LastName, (e.TotalLeaves - e.LeavesTaken)) }
//main.go文件
package main import "oop/employee" func main() { e := employee.Employee { FirstName: "Sam", LastName: "Adolf", TotalLeaves: 30, LeavesTaken: 20, } e.LeavesRemaining() }

1.Go 並不支持構造器。若是某類型的零值不可用,須要程序員來隱藏該類型,避免從其餘包直接訪問。程序員應該提供一種名爲 NewT(parameters) 的 函數,按照要求來初始化 T 類型的變量。  oop

2.應該讓 Employee 結構體不可引用,修改 Employee爲employee,這樣別的文件就不能引用。post

//employee.go文件
package employee import ( "fmt" ) type employee struct { firstName string lastName string totalLeaves int leavesTaken int } func New(firstName string, lastName string, totalLeave int, leavesTaken int) employee { e := employee {firstName, lastName, totalLeave, leavesTaken} return e } func (e employee) LeavesRemaining() { fmt.Printf("%s %s has %d leaves remaining", e.firstName, e.lastName, (e.totalLeaves - e.leavesTaken)) }
//main.go文件
package main import "oop/employee" func main() { e := employee.New("Sam", "Adolf", 30, 20) e.LeavesRemaining() }  

總結:Go 不支持類,但結構體可以很好地取代類,而以 New(parameters) 簽名的方法能夠替代構造器。學習

 

組合取代繼承

Go 不支持繼承,但它支持組合(Composition)。組合通常定義爲「合併在一塊兒」。汽車就是一個關於組合的例子:一輛汽車由車輪、引擎和其餘各類部件組合在一塊兒。網站

在 Go 中,經過在結構體內嵌套結構體,能夠實現組合。

組合的典型例子就是博客帖子。每個博客的帖子都有標題、內容和做者信息。使用組合能夠很好地表示它們。經過學習本教程後面的內容,咱們會知道如何實現組合。

package main

import (  
    "fmt"
)

type author struct {  
    firstName string
    lastName  string
    bio       string
}

func (a author) fullName() string {  
    return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}

type post struct {  
    title   string
    content string
    author
}

func (p post) details() {  
    fmt.Println("Title: ", p.title)
    fmt.Println("Content: ", p.content)
    fmt.Println("Author: ", p.fullName())
    fmt.Println("Bio: ", p.bio)
}

func main() {  
    author1 := author{        
        "Naveen",        
        "Ramanathan",        
        "Golang Enthusiast",
    }
    post1 := post{        
        "Inheritance in Go",        
        "Go supports composition instead of inheritance",
        author1,
    }
    post1.details()
}
Title:  Inheritance in Go
Content:  Go supports composition instead of inheritance
Author:  Naveen Ramanathan
Bio:  Golang Enthusiast

  

結構體切片的嵌套

package main

import (  
    "fmt"
)

type author struct {  
    firstName string
    lastName  string
    bio       string
}

func (a author) fullName() string {  
    return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}

type post struct {  
    title   string
    content string
    author
}

func (p post) details() {  
    fmt.Println("Title: ", p.title)
    fmt.Println("Content: ", p.content)
    fmt.Println("Author: ", p.fullName())
    fmt.Println("Bio: ", p.bio)
}

type website struct {  
     posts []post
}

func (w website) contents() {  
    fmt.Println("Contents of Website\n")    
    for _, v := range w.posts {
        v.details()
        fmt.Println()
    }
}
    
func main() {  
    author1 := author{        
        "Naveen",        
        "Ramanathan",        
        "Golang Enthusiast",
    }
    post1 := post{        
        "Inheritance in Go",        
        "Go supports composition instead of inheritance",
        author1,
    }
    post2 := post{        
        "Struct instead of Classes in Go",        
        "Go does not support classes but methods can be added to structs",
        author1,
    }
    post3 := post{        
        "Concurrency",        
        "Go is a concurrent language and not a parallel one",
        author1,
    }
    w := website{
        posts: []post{post1, post2, post3},
    }
    w.contents()
}

在上面的主函數中,咱們建立了一個做者 author1,以及三個帖子 post1post2和 post3。咱們最後經過嵌套三個帖子,在第 62 行建立了網站 w,並在下一行顯示內容。

程序會輸出:

Contents of Website

Title:  Inheritance in Go  
Content:  Go supports composition instead of inheritance  
Author:  Naveen Ramanathan  
Bio:  Golang Enthusiast

Title:  Struct instead of Classes in Go  
Content:  Go does not support classes but methods can be added to structs  
Author:  Naveen Ramanathan  
Bio:  Golang Enthusiast

Title:  Concurrency  
Content:  Go is a concurrent language and not a parallel one  
Author:  Naveen Ramanathan  
Bio:  Golang Enthusiast

  

使用接口實現多態

Go 經過接口來實現多態。在 Go 語言中,咱們是隱式地實現接口。一個類型若是定義了接口所聲明的所有方法,那它就實現了該接口。

一、多個類型能夠實現同一個接口。 
二、一個類型能夠實現多個接口。

package main

import (
    "fmt"
)

type Income interface {
    calculate() int
    source() string
}

type FixedBilling struct {
    projectName string
    biddedAmount int
}

type TimeAndMaterial struct {
    projectName string
    noOfHours  int
    hourlyRate int
}

func (fb FixedBilling) calculate() int {
    return fb.biddedAmount
}

func (fb FixedBilling) source() string {
    return fb.projectName
}

func (tm TimeAndMaterial) calculate() int {
    return tm.noOfHours * tm.hourlyRate
}

func (tm TimeAndMaterial) source() string {
    return tm.projectName
}

func calculateNetIncome(ic []Income) {
    var netincome int = 0
    for _, income := range ic {
        fmt.Printf("Income From %s = $%d\n", income.source(), income.calculate())
        netincome += income.calculate()
    }
    fmt.Printf("Net income of organisation = $%d", netincome)
}

func main() {
    project1 := FixedBilling{projectName: "Project 1", biddedAmount: 5000}
    project2 := FixedBilling{projectName: "Project 2", biddedAmount: 10000}
    project3 := TimeAndMaterial{projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
    incomeStreams := []Income{project1, project2, project3}
    calculateNetIncome(incomeStreams)
}

在上面的 main 函數中,咱們建立了三個項目,有兩個是 FixedBilling 類型,一個是 TimeAndMaterial 類型。接着咱們建立了一個 Income 類型的切片,存放了這三個項目。因爲這三個項目都實現了 Interface 接口,所以能夠把這三個項目放入 Income 切片。最後咱們將該切片做爲參數,調用了 calculateNetIncome 函數,顯示了項目不一樣的收益和收入來源。  

Income From Project 1 = $5000
Income From Project 2 = $10000
Income From Project 3 = $4000
Net income of organisation = $19000 

 

refer:https://studygolang.com/articles/12681

相關文章
相關標籤/搜索