Go 面向物件 - New() 函式 替代 建構函式

我們在 Go 面向物件 - Structs 替代 Classes 這篇文章中寫的程式看起來不錯,但其中有一個微妙的問題。 讓我們看看當我們用零值定義

employee

結構體時會發生什麼。 將 main。go 的內容替換為以下程式碼

package mainimport “oop/employee”func main() { var e employee。Employee e。LeavesRemaining()}

我們所做的唯一改變是在第6行建立一個零值的 employee。該程式將輸出以下內容

has 0 leaves remaining

Go 面向物件 - New() 函式 替代 建構函式

正如你所見,使用

Employee

的零值建立的變數不可用。它沒有有效的 first name、last name,也沒有有效的 leave 詳情。

在java等其他OOP語言中,這個問題可以透過使用建構函式來解決。可以使用引數化建構函式建立有效物件。

Go 不支援建構函式。如果型別的零值不可用,則程式設計師的工作是取消匯出該型別以防止其他包訪問,並提供一個名為

NewT(parameters)

的函式,該函式使用所需的值初始化型別

T

。將建立 T 型別值的函式命名為

NewT(parameters)

是 Go 中的約定。它將充當建構函式的角色。如果包只定義了一種型別,那麼 Go 中的約定就是將此函式命名為

New(parameters)

而不是 **NewT(parameters)**。

讓我們對我們編寫的程式進行更改,以便每次建立 Employee 時都可以使用它。

第一步是取消匯出 Employee 結構體並建立一個函式

New()

來建立一個新的 Employee。將employee。go中的程式碼替換為以下內容

package employeeimport ( “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\n”, e。firstName, e。lastName, (e。totalLeaves - e。leavesTaken))}

我們在這裡做了一些重要的更改。我們在第7行將

Employee struct

的起始字母

E

改為小寫,即我們將 Employee struct 型別改為 employee struct 型別。透過這樣的修改,我們成功地取消了 employee 結構體的匯出並阻止了其他包的訪問。將未匯出結構體的所有欄位也設為未匯出是一種很好的做法,除非有特定需求需要你匯出它們。由於我們不需要在employee 包之外的任何地方訪問employee 結構體的欄位,因此我們也取消了所有欄位的匯出。

我們在

LeavesRemaining()

方法中相應地更改了欄位名稱。

現在,由於 employee 未匯出,因此無法從其他包建立 employee 型別的值。因此,我們提供了一個匯出用的 New 函式。 它將所需的引數作為輸入並返回一個新建立的 employee。

該程式仍需進行更改以使其正常工作,但讓我們執行它以瞭解到目前為止所做更改的效果。如果執行此程式,它會失敗並顯示以下編譯錯誤

# oop。/main。go:6:8: undefined: employee。Employee

這是因為我們在 employee 包中有一個未匯出的員工,並且無法從主包中訪問它。 因此編譯器會丟擲一個錯誤,表明該型別未在 main。go 中定義。 完美的。 正是我們想要的。 現在沒有其他軟體包能夠建立零值 employee 。 我們已成功阻止建立不可用的 employee 結構體值。 現在建立員工的唯一方法是使用 New 函式。

將 main。go 的內容替換為以下內容

package main import “oop/employee”func main() { e := employee。New(“Sam”, “Adolf”, 30, 20) e。LeavesRemaining()}

對該檔案的唯一更改是第6行。透過將所需引數傳遞給新 New 函式,我們建立了一個新 employee(員工)。

下面是進行必要更改後的兩個檔案的內容。

employee.go

package employeeimport ( “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\n”, 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 install oop$ oopSam Adolf has 10 leaves remaining

Go 面向物件 - New() 函式 替代 建構函式

因此你可以理解,雖然 Go 不支援類,但可以有效地使用結構體代替類,並且可以使用全域性函式 New(parameters) 來代替建構函式。

和 Go 面向物件 - Structs 替代 Classes 這篇文章一起,構成了 Go 中的類和建構函式。