GO語言物件導向編程之方法
來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。#GO語言物件導向編程之方法(上)#<font size=5>學過C++或者JAVA的程式員,對於物件導向編程應該是很熟悉的。大家都知道物件導向編程的三大基本特徵:封裝,繼承,多態。在GO語言中,簡化了很多物件導向編程的概念,比如 繼承,虛函數,建構函式,解構函式,隱藏指標等。對於接觸過物件導向編程的人來說,GO語言的物件導向編程更加的簡單易懂。</font>##方法(類)的定義<font size = 4>在函式宣告時,在其名字之前放上一個變數,即是一個方法。這個附加的參數會將該函數附加到這種類型上,即相當於為這種類型定義了一個獨佔的方法。</font>package mainimport "math"import "fmt"type Point struct {x float64y float64}func TraDistance(p1 Point, p2 Point) float64 {return math.Hypot(p1.x-p2.x, p1.y-p2.y)}func (p1 Point) ObjDistance(p2 Point) float64 {return math.Hypot(p1.x-p2.x, p1.y-p2.y)}func main() {p1 := Point{10, 20}p2 := Point{20, 10}old_len := TraDistance(p1, p2)new_len := p1.ObjDistance(p2)fmt.Println("The result of old method is ", old_len)fmt.Println("The result of OBJ method is ", new_len)}<font color = red>在Go語言裡,我們為一些簡單的數值、字串、slice、map來定義一些附加行為很方便。方法可以被聲明到任意類型,只要不是一個指標或者一個interface。</font>****##指標對象引入指標對象的原因在於GO語言和C語言一樣,都是基於值傳遞的,什麼意思哪,就是你調用函數的時候,對對象的值進行了拷貝,所以是沒法修改對象內部的值的,看下面的例子:type Shape struct {length float64height float64weight float64}func (s Shape) ChangeHeight(value float64) {s.height = value}triangle := Shape{1, 3, 4}triangle.ChangeHeight(10)fmt.Println(triangle.height) //輸出3func (s *Shape) ChangeHeightWithPoint(value float64) {s.height = value}triangle := Shape{1, 3, 4}//(&triangle).ChangeHeightWithPoint(10)//triangle.ChangeHeightWithPoint(10) fmt.Println(triangle.height) //上面兩種調用方法都可以改變對象的值對於第二種為什麼兩種方法都可以調用哪?因為GO語言幫我們做了隱式轉換,當然我們也可以用指標來調用非指標的,就像上面的第triangle.ChangeHeight(10)也可以寫成(&triangle).ChangeHeight(10),同樣的GO語言也會幫你隱式轉換成非指標。***##通過嵌入式結構體擴充類型(類似繼承)前面的時候說過結構體的嵌入和匿名函數。我們看下面的一個例子:type Point struct {x float64y float64}type Shape struct {Pointlength float64height float64weight float64}func (p1 Point) ObjDistance(p2 Point) float64 {return math.Hypot(p1.x-p2.x, p1.y-p2.y)}p1 := Point{10, 20}p2 := Point{20, 10}triangle := Shape{p1, 1, 3, 4}len := triangle.ObjDistance(p2)fmt.Println(len)Shape是可以直接對Point對象的函數進行調用的,看到這裡是不是感覺這就是c++裡面的繼承,那我們再看下面這個例子:p1 := Point{10, 20}p2 := Point{20, 10}triangle := Shape{p1, 1, 3, 4}triangle2 := Shape{p2, 1, 3, 4}fmt.Printf("The point2 value in triangle2 x=%f,y=%f", triangle2.x, triangle2.y)len := triangle.ObjDistance(triangle2)這個時候編譯器會有下面的錯誤:<font color = red>cannot use triangle2 (type Shape) as type Point in argument to triangle.Point.ObjDistance</font>對於函數ObjDistance來說,參數Point類型不能用Shape類型,即使Shape類型可以直接存取Point的變數.但對於c++或者java來說,子類是可以作為參數傳遞的,如下面的代碼:#include<iostream> using namespace std;class Parent{public:int x = 10 ,y = 20;};class Child : public Parent{public:int m,n;};int test(Parent s){cout << s.x <<s.y; }int main(){Child childObj;test(childObj);//編譯和運行沒問題} 所以GO語言的“繼承”並不等同於其它物件導向語言的繼承。***##方法值和方法運算式方法的值:func (p1 Point) ObjDistance(p2 Point) float64 {return math.Hypot(p1.x-p2.x, p1.y-p2.y)}p1 := Point{10, 20}p2 := Point{20, 10}p1Func := p1.ObjDistancep1Func(p2)方法的運算式:func (p1 Point) ObjDistance(p2 Point) float64 {return math.Hypot(p1.x-p2.x, p1.y-p2.y)}p1 := Point{10, 20}p2 := Point{20, 10}p2Func := Point.ObjDistancep2Func(p1, p2)方法的運算式看著比函數多了一個參數,這是因為方法的運算式會把第一個參數作為接收器,後面的參數才是函數的真正參數。##封裝在C++裡面,我們使用public,private,protected關鍵字來作為變數或者函數的使用權限設定,但在Go語言中,前面已經說過,GO語言只有大小寫區別,如果想把函數或者變數暴露在外部,那麼就首字母大寫,相反則小寫。</font>291 次點擊