Go 語言基礎系列(七):面向對象編程之結構體
階段小結
通過前面的學習,我們對常量、變量、運算符,流程控制,容器,函數以及包等概念有了基本的理解。並且瞭解了這些概念的一種協作關係:常量和變量都是數據的一種載體,數據通過不同的運算符參與運算時,對計算的流程進行一定程度的控制便是流程控制,並且對於較多的數據通過內置容器進行存儲,然後通過對以上的所有概念進行整合,通過函數完成某一特定的功能。相同類型的函數在同一文件中進行呈現,最後對越來越多的文件通過包的方式對代碼進行最有效的管理(大家可以試着回想一下我們前面學習的概念, 部分遺忘的話可以再回顧一下)。
以上是我們接觸和學習一種新高級編程語言的較爲通用的一套方式,這樣的話可以對編程語言的整體進行一個很好的把握。那麼在此基礎之上,我們深入語言要進一步學習語言的思想、特性及功能實現等等。所以,我們以 Golang 爲例,從本篇開始將對語言自身的特點(也有可能是區別於其他語言獨有的特點)進行學習。
本篇以及下一篇文章我們學習 Golang 的面向對象編程的思想,分別介紹結構體和接口。首先,請大家記住一句話:Golang 語言是通過結構體和接口來實現面向對象編程的思想。因爲對於一種 “思想”,需要我們在實踐的過程中不斷的學習和領會,不同的階段,不同的經驗積累,都會有不同的新的感悟。
這裏,我們對面向過程編程和麪向對象編程兩種思想進行非常簡短的介紹,大家先有一個基本的概念,之後我們會寫一篇軟件編程的發展史的文章,在裏面再更進一步的說明,但是,還是強烈建議大家:實踐再實踐,實踐中思考,不斷的去領會。
首先,可以說,對於面向過程和麪向對象兩種編程方式,沒有哪一種更好,都是不同時期的產物。面向過程編程方式是先於面向對象編程方式出現的,在最初的軟件開發中,主要從業務的具體過程實現出發。過程實現會導致代碼的複用性差,複用差的代碼也難以擴展,並且複用性差會導致更多的代碼重複,這樣的話代碼的維護性就會降低,我們知道軟件的穩定性是最重要的,但是早期的軟件工程較小,這些影響並不會成爲主要因素,而且由於沒有太多的實例化調用(此爲面向對象編程裏的概念),所以性能還更好。但是隨着軟件編程的不斷髮展,軟件工程越來越龐大,軟件的可維護性,可複用性和可擴展性變得越來越重要,所以出現了面向對象的編程方式。
面向對象編程的三個特點:封裝,繼承和多態。我們在後面的介紹中會展開介紹
思維邏輯圖如下:
下面我們從以上四個方面對 **結構體 **進行相應的介紹
** 結構體的聲明 **
結構體是對現實中存在的實體對象的一次抽象,也是一次封裝 (面向對象)
結構體由成員變量構成,而成員變量是對現實對象屬性的不同表示
以開發者爲例,具有如下屬性:姓名,性別,年齡,工號,部門等
結構體聲明通過關鍵字 type 和 struct 實現,標準格式如下:
type 結構體名字 struct {
** 成員變量 1 類型 1
**
** 成員變量 2 類型 2
**
** 成員變量 3 類型 3
**
** ...
**
}
注:1)同一結構體,成員變量名不同相同
2)相同類型的成員變量可以通過如下形式:成員變量 1,成員變量 2 類型
3)同一包內,不能結構體同名
4)不同的包,如希望結構體或者成員變量可導出,可通過首字母大寫的方式實現
**示例:**聲明一個 developer 結構體
** 結構體實例化及初始化 **
01
** 普通結構體的實例化 **
結構體的使用需要先聲明後實例化,然後才能進行使用。實例化的方式有三種:標準實例化,取地址實例化和 new 函數實例化
1)標準實例化:標準實例化是通過 var 關鍵字完成,格式如下:
var 結構體實例名稱 結構體類型名
例如,聲明並實例化一個名爲 developer1 的 developer 結構體類型
2)取地址實例化:通過獲取指針地址符號 & 加 結構體類型名完成,格式如下:
結構體實例名 := & 結構體類型名 {}
同樣,聲明並實例化一個名爲 developer1 的 developer 結構體類型
結果如下:
2)new 函數實例化:返回結構體的指針類型,格式如下:
結構體實例名 := new(結構體類型名)
同樣,聲明並實例化一個名爲 developer1 的 developer 結構體類型
結果如下:
02
** 普通結構體初始化 **
結構體初始化即是對結構體中的成員變量進行賦值,主要有三種形式:1)聲明後通過 **點. **訪問成員變量進行賦值;2)聲明的同時以 map 初始化的方式初始化;3)聲明的同時按成員變量聲明順序按序賦值;
1)聲明後通過 點.****訪問成員變量進行賦值
結果如下:
2)聲明的同時以 map 初始化的方式初始化
結果如下:
3)聲明的同時按成員變量聲明順序按序賦值
03
** 匿名結構體實例化及初始化 **
匿名結構體的初始化不需要 type 關鍵字,也不需要結構體類型名。格式如下:
**結構體實例名 := struct { **
** 成員變量 1 類型 1
**
** 成員變量 2 類型 2
**
** 成員變量 3 類型 3**
** ...
**
} {
** 成員變量 1:變量值 1,
**
** 成員變量 2:變量值 2,**
** 成員變量 3:變量值 3,**
** ...
**
}
示例:
結果如下:
解釋:示例中成員變量的值的初始化爲可選的,我們可以在實例化時先不進行初始化,後面可以通過 **點 . 訪問成員變量進行賦值,**或者直接進行初始化
** 結構體方法 **
首先,在 Golang 語言中,方法和函數兩個概念是不相同的,前面的文章中我們已經介紹過函數的概念,那麼方法是什麼呢?方法是具有接收者的函數。
接收者可分爲:指針變量接收者和值變量接收者
**
01
** 指針變量接收**
**
指針變量接收者,**帶 ***
func (結構體接收者名 * 結構體類型) 方法名(入參){
** 方法體
**
}
結果如下:
**02
**
**** 值變量接收****
值變量接收者,**不****帶 ***
func (結構體接收者名 結構體類型) 方法名(入參){
** 方法體
**
}
結果如下:
總結:值類型接收者不可以修改結構體成員變量,如需要修改結構體成員變量,應使用指針類型接收者
** 結構體內嵌 **
面向對象編程思想的第二特點:繼承。在 Golang 中,結構體內嵌體現了面向對象編程的 “繼承” 特點
01
** 內嵌普通結構體 **
格式如下:
type 結構體 1 名 struct {
** 成員變量 1 類型 1
**
}
type 結構體 2 名 struct {
** 結構體 1 名**
** 成員變量 2 類型 2
**
}
示例:developer 可以分屬於不同的國家
結果如下:
分析:結構體 developerInDeferentCountry 結構體內嵌了 developer 結構體,並且擁有了結構體 developer 的方法
02
** 內嵌匿名結構體 **
對於內嵌匿名結構體,格式如下:
type 結構體 1 名 struct {
** 結構體 2 名 struct {**
** 成員變量 類型
**
** } **
** 成員變量 類型
**
}
但是,在內嵌匿名結構體中,對結構體初始化時,初始化匿名結構體,仍需再次聲明結構體,如下示例:
分析:示例中,main 函數中對結構體初始化時,由於是匿名結構體內嵌,所以需再次聲明結構體
到此關於 Golang 面向對象編程之結構體的分享就結束了~
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Na4Y6Wg5-GzIPMENERy6jA