前言:
Golang 相似與C語言, 基礎文法與C基本一致,除了廣受爭議的 左花括弧 必須與代碼同行的問題, 別的基本差不多;
學會了C, 基本上萬變不離其宗, 現在的進階語言身上都能看到C的影子;
Golang 中的 物件導向
什麼是物件導向?
- 物件導向是一種編程思想, 並不是某一種開發語言獨屬;
那什麼是對象?
- 對象,指的是客體。所謂客體是指客觀存在的對象實體和主觀抽象的概念。(擴充閱讀)
- 簡單理解就是, 抽象一個擁有多重屬性的客體, 將共有屬性抽離出來為一個類, 以便實現定義多個客體的功能。
物件導向有哪些特徵?
- 物件導向 通常包括三個特徵 繼承, 封裝 和 多態; (簡單理解)
- 繼承: 由子類繼承父類的屬性/資料/方法等;
- 封裝: 以最簡單的函數形式將方法展示出去, 而不需要使用者知道方法內有什麼、由什麼實現, 類似黑盒子, 只需知道怎麼用, 毋需知道為什麼;例如, 電動車充電器, 只需知道插上兩邊的插頭, 而不需要去理解如何變壓限流;
- 多態: 一種方法的多種表現形式, 可以看作是封裝後的方法的集合, 根據使用情境, 自動分發到某具體方法中; 即一個同樣的函數對於不同的對象可以具有不同的實現。
為什麼使用物件導向?
-
物件導向是為瞭解決系統的可維護性,可擴充性,可重用性(詳細資料)
- 簡單理解: 以對象方法代替過程完成實現, 方便以後修改及複用
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 mainimport "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中的物件導向有了一個基礎的認識, 但是對於物件導向本身還是需要多加鞏固和練習;
學習是為了寫代碼, 不多寫代碼怎麼學習;