大家好,我是Mandy。
前面一篇,分享了Go中的函數和方法之間有什麼區別、如何使用,今天來分享一篇關於面向對象的知識。
萬丈高樓平地起
在學習之前,我們來普及一下關於面向對象的基礎知識。
什麼是面向對象
面向對象(Object-Oriented)是一種計算機編程的方法和思想,它將程序中的數據(對象)和操作(方法)組織成一個個相互關聯和交互的對象。對象是現實世界中的事物或概念在計算機程序中的抽象表示。
面向對象編程的核心思想是將問題分解為一組相互作用的對象,每個對象都具有自己的狀態(屬性或數據)和行為(方法或操作),並通過對象之間的消息傳遞來進行協作和交互。
總結一句,面向對象就是將一些具有相同特性的事物,通過類的形式進行統一封裝。封裝的類中的屬性和方法,就是事物間具有相同的特徵和行為。例如,人有身高、體重和跑步的行為。身高和體重對應類中的屬性,跑步對應類中的方法。
面向對象的優勢
面向對象有幾大特點,封裝、繼承和多態,針對這些特點,可以總結出如下的幾個優勢:
1、模塊化和可重用性:面向對象編程允許將代碼組織成獨立的對象或類,每個對象都具有特定的功能和行為。這種模塊化的方式使代碼更易於理解、維護和重用,可以提高開發效率。
2、封裝和信息隱藏:面向對象編程通過封裝將數據和相關方法封裝在對象內部,隱藏了對象的實現細節,只暴露必要的接口。這樣可以防止外部代碼直接訪問和修改對象的內部狀態,提高代碼的安全性和可靠性。
3、繼承和代碼複用:繼承是面向對象編程的一個重要概念,它允許通過從現有類派生出新類來擴展和重用代碼。子類可以繼承父類的屬性和方法,並可以添加、修改或覆蓋這些屬性和方法,從而實現代碼的複用和擴展。
4、多態和靈活性:多態是面向對象編程的另一個重要概念,它允許同一種行為有不同的表現形式。通過多態,可以根據對象的實際類型來調用相應的方法,這樣可以增加代碼的靈活性和可擴展性。
5、更易於理解和維護:面向對象編程提供了一種自然的思維方式,能夠更好地模擬和表示現實世界的概念和關係。這樣使得代碼更易於理解、調試和維護,減少了代碼的複雜性和耦合性。
總的來説,面向對象編程語言提供了一套豐富的概念和技術,在代碼結構、複用性、可維護性和靈活性等方面具有明顯的優勢,使得軟件開發更加高效和可靠。
Go中的面向對象
相信從你剛開始學習Go時,以及使用Go參與項目,都知道Go中沒有面向對象這樣的概念。但在實際的項目開發中,為了提高代碼的可維護性、可擴展性和可複用性等特點,你不得不使用面向對象的設計理念來編碼。
那該怎麼實現呢,答案就是使用Go中結構體來實現。
需要注意的是,本文不會單獨去講結構體的語法內容。重點是總結結構體與面向對象的區別。
什麼是結構體
在Go語言中,結構體(Struct)是一種自定義數據類型,用於組織和存儲一組相關字段的集合。它類似於其他編程語言中的類或對象,是一種將數據和相關方法組合在一起的容器。
1、結構體的字段就類似於面向對象中的屬性。
2、結構體的方法就類似於面向對象中的方法。
要定義一個結構體非常的簡單,其語法格式如下:
type 結構體名稱 struct {
字段名 字段屬性
}
func (接受者) 方法名稱([方法參數]) [方法返回值] {
}
下面我們就來實際定義一個結構體。
package main
import "fmt"
type Animal struct {
name string
age string
height float64
weight float64
}
func (u Animal) run() {
fmt.Println(u.name, "跑步的速度很快")
}
func main() {
animal1 := &Animal{
name: "鴕鳥",
}
animal1.run()
// output:鴕鳥 跑步的速度很快
}
1、定義一個名為Animal的結構體,就相當於面向對象中的類。
2、定義name、age等字段,就相當於面向對象中的屬性。
3、定義run()方法,就相當於面向對象中的方法。記住:方法一定是要有一個接收者的,這裏的接收者為結構體Animal,其實就是將這個方法歸屬到結構體Animal。就好比在類中定義一個方法,這個方法就是屬於這個類。
4、使用&Animal{},就相當於面向對象的實例化類的過程。
5、使用animal1.run(),就相當於實例化了一個對象,通過對象去調用方法。
是不是發現使用struct,實現面向對象是非常簡單。
對象繼承
在具有面向對象的開發語言中,使用對象繼承,都是使用關鍵字extend關鍵字來實現。在Go中,可以使用結構體嵌套的方式來實現繼承關係。
package main
import "fmt"
type Animal struct {
name string
age string
height float64
weight float64
}
type Dog struct {
Animal
color string
}
func (u Animal) run() {
fmt.Println(u.name, "跑步的速度很快")
}
func (d Dog) sleep() {
fmt.Println(d.name, "晚上很少睡覺")
}
func main() {
dog := &Dog{
Animal{name: "小狗"},
}
dog.sleep()
dog.run()
}
1、上述定義了一個Animal的結構體,作為父類結構體。同時定義了一個run()方法,當做父類的方法,定義了4個字段當做父類的屬性。
2、接着定義了一個Dog結構體,嵌入了一個Animal的結構體,此時兩個結構體就實現了一個繼承的關係。
3、Dog結構體自身也定義了一個sleep()的方法。這時,Dog結構體具備父類結構體的所有方法和屬性,同時也有自己的屬性和方法。
需要注意的是,結構體的嵌套,可以是外部包,也可以是本包。方法的接收者必須是本包的結構體,不能是外部包。
此致,結構體實現對象的特性,就總結的差不多了。記住Go中的機構體不僅能實現面向對象的特性,同時還具有其他更強大的功能。這裏簡單的舉例。
type user struct {
name string `json:"name"`
}
上面的寫法,相信大家在很多的第三方包,以及項目開發中都能遇到。通過定義一個tag,可以將元數據通過tag的定義方式,暴露給外部。
總結
在Go語言中,struct是一種用户自定義的數據類型,用於組織和存儲不同字段類型的數據。它類似於其他編程語言中的結構體,但在Go中,struct不具備面向對象編程中類的所有特性。以下是struct與面向對象的主要區別:
1、繼承:Go語言中的struct不支持繼承,無法通過一個struct來繼承另一個struct的成員和方法。而面向對象編程中,類之間可以通過繼承來共享和擴展功能。
2、封裝:在面向對象編程中,類的成員和方法可以進行封裝,通過訪問修飾符來控制其可見性。而在Go中,struct的成員默認是公開的,可以被外部訪問,無法像類一樣進行嚴格封裝。
3、多態:面向對象編程支持多態性,一個對象可以根據不同的上下文表現出不同的行為。而Go語言中的struct不直接支持多態,但可以通過接口來實現類似的效果。
總的來説,雖然Go語言的struct不同於傳統的面向對象編程語言中的類,但通過結合使用接口、嵌入等語言特性,我們仍然可以在Go中實現類似面向對象的設計和編程範式。