前言:
Golang 相似與C語言, 基礎語法與C基本一致,除了廣受爭議的 左花括號 必須與代碼同行的問題, 別的基本差不多;
學會了C, 基本上萬變不離其宗, 現在的高級語言身上都能看到C的影子;
Golang 中的 面向對象
-
什么是面向對象?
- 面向對象是一種編程思想, 並不是某一種開發語言獨屬;
-
那什么是對象?
- 對象,指的是客體。所謂客體是指客觀存在的對象實體和主觀抽象的概念。(擴展閱讀)
- 簡單理解就是, 抽象一個擁有多重屬性的客體, 將共有屬性抽離出來為一個類, 以便實現定義多個客體的功能。
-
面向對象有哪些特征?
- 面向對象 通常包括三個特征 繼承, 封裝 和 多態; (簡單理解)
- 繼承: 由子類繼承父類的屬性/數據/方法等;
- 封裝: 以最簡單的函數形式將方法展示出去, 而不需要使用者知道方法內有什么、由什么實現, 類似黑盒子, 只需知道怎么用, 毋需知道為什么;例如, 電動車充電器, 只需知道插上兩邊的插頭, 而不需要去理解如何變壓限流;
- 在Go語言中, 通常使用接口的方式完成封裝;
- 多態: 一種方法的多種表現形式, 可以看作是封裝后的方法的集合, 根據使用場景, 自動分發到某具體方法中; 即一個同樣的函數對於不同的對象可以具有不同的實現。
- 面向對象 通常包括三個特征 繼承, 封裝 和 多態; (簡單理解)
-
為什么使用面向對象?
-
面向對象是為了解決系統的可維護性,可擴展性,可重用性( 詳細資料)
- 簡單理解: 以對象方法代替過程完成實現, 方便以后修改及復用
-
-
Go語言中的面向對象如何實現? 以簡單計算器為例
- 抽象類型: 計算器, 可以抽象為 兩個數字, 一個運算符和結果返回值;
- 父類: 兩個數字
- 子類: 繼承父類
- 子類的方法: 做出計算並輸出結果返回值
- 定義方法, 對不同的運算符返回不同的運算結果
- 封裝: 定義接口, 將子類方法進行封裝
- 多態: 定義多態, 並將封裝好的接口作為形參, 實現多態; 可以簡單理解為 以接口作為形參的函數
- 抽象類型: 計算器, 可以抽象為 兩個數字, 一個運算符和結果返回值;
基於面向對象的, Go語言實現簡單計算器
1. 分析實現過程, 進行抽象化: 兩個數字, 一個運算符, 一個結果返回值
type BaseNum struct { num1 int num2 int } // BaseNum 即為父類型名稱 type Add struct { BaseNum } //加法子類, 定義加法子類的主要目的, 是為了定義對應子類的方法 type Sub struct { BaseNum } //減法子類
2. 定義子類方法, 實現運算及返回值
func (a *Add)Opt()(value int) { return a.num1 + a.num2 }//加法的方法實現 func (s *Sub)Opt()(value int) { return s.num1 + s.num2 }//減法的方法實現
注意: 這里的方法名稱是一樣的, 這樣才能使用接口進行歸納;
3. 封裝, 定義接口, 歸納子類方法為 接口
type Opter interface { //接口定義 Opt()int //封裝, 歸納子類方法, 注意此處需要加上返回值, 不然沒有辦法輸出返回值(因為方法中使用了返回值) }
4. 定義多態
func MultiState(o *Opter)(value int) { //多態定義, 可以簡單理解為以接口作為形參的函數, 方便學習 value = o.Opt() return }
5.主函數及調用
func main(){ var a Add = Add{BaseNum{2,3}} //使用Add對象方法 value := a.Opt() //使用接口 var i Opter i = &a value := i.Opt() //使用多態 i = &a value := MultiState(i) //輸出測試 fmt.Println(value) }
至此, 一個單純的面向對象的 簡單計算器完工;
引發的問題思考:
為什么比面向過程復雜的多?是否有意義?
答案是肯定的, 面向對象所擁有的擴展性與維護性是面向過程無法比擬的;
假設我需要在以上加減法計算器上加一個乘法或者除法, 那么我們需要做的工作僅僅是新建一個類和對應的方法就可以了, 其余的事情已經由接口定義下過了;
點滴延伸:
三 面對對象編程,分為幾個步驟?
面向對象是一種思想,他讓我們在分析和解決問題時,把思維和重點轉向現實中的客體中來,然后通過UML工具理清這些客體之間的聯系,最后用面向對象的語言實現這種客體以及客體之間的聯系。它分為面向對象的分析(OOA),面向對象的設計(OOD),面向對象的編程實現(OOP)三個大的步驟。
1、首先是分析需求,先不要思考怎么用程序實現它,先分析需求中穩定不變的客體都是些什么,這些客體之間的關系是什么。
2、把第一步分析出來的需求,通過進一步擴充模型,變成可實現的、符合成本的、模塊化的、低耦合高內聚的模型。
3、使用面向對象的實現模型
摘自http://www.cnblogs.com/seesea125/archive/2012/04/20/2458940.html
在上面的實例中, 我們提到了運算符, 並將運算符與輸入值和輸出值並列在一塊, 這是為什么呢?
因為我們可以通過實現模型來完成更加簡潔的寫法:
下面實例使用工廠模式來解決計算器的問題:
package main import "fmt" /* 實例: 面向對象的計算器實現 1.定義父類 2.定義子類,以及子類的方法 運算實現 3.定義接口, 歸納 子類方法 4.定義空類, 定義空類的方法,即 工廠模式, 將 運算符 與 數值 分開處理, 以運算符來分發方法, 方便調用 5.定義一個多態, 將接口歸納, 方便調用 6.主函數, 初始化, 調用工廠模式, 進行驗證 */ //父類 type BaseNum struct { num1 int num2 int } //加法子類 type Add struct { BaseNum } //減法子類 type Sub struct { BaseNum } //子類方法 func (a *Add)Opt() int { return a.num1 + a.num2 } func (s *Sub)Opt() int { return s.num1 - s.num2 } //定義接口, 即封裝 type Opter interface { Opt() int } //定義多態 func MultiState(o Opter) int{ value:=o.Opt() return value } //定義空類 以產生 工廠模式 的方法 type Factory struct { }
//⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️ func (f *Factory)FacMethod(a,b int,operator string) (value int){ var i Opter switch operator { case "+": var AddNum Add = Add{BaseNum{a,b}} i = &AddNum case "-": var SubNum Sub = Sub{BaseNum{a,b}} i = &SubNum } //接口實現 : value = i.Opt() value = MultiState(i) //多態實現 return } //⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️ func main() { var a Factory value := a.FacMethod(20,3,"-") fmt.Println(value) }
上面的代碼中, 我們看到 Factory 部分, 先定義了一個空類以完成對平級方法的調用, 而后定義了一個方法;
此方法代替了主函數中每次調用前的初始化操作, 而且, 在主函數中, 也完全不需要知道其中的實現過程;
基於本實例的簡單分析, 及對Golang面向對象簡單圖示:
小結:
至此, 關於Golang中的面向對象有了一個基礎的認識, 但是對於面向對象本身還是需要多加鞏固和練習;
學習是為了寫代碼, 不多寫代碼怎么學習;