Golang系列(二)之面向物件程式設計
- 面向物件程式設計:
把一組資料結構和處理它們的方法組成物件(object),把相同行為的物件歸納為類(class),通過類的封裝(encapsulation)隱藏內部細節,通過繼承(inheritance)實現類的特化(specialization)[方法的重寫,子類不同於父類的特性]/泛化(generalization)[共性,子類都擁有父類的特性],通過多型(polymorphism)實現基於物件型別的動態分派(dynamic dispatch)。
- 面對物件思想:
面向物件思想是對現實世界事物的抽象,系統中一切事物皆為物件;物件是屬性及其操作的封裝體;物件可按其性質劃分為類,物件成為類的例項;例項關係和繼承關係是物件之間的靜態關係;訊息傳遞是物件之間動態聯絡的唯一形式,也是計算的唯一形式;方法是訊息的序列。
(一)型別系統[類的宣告]
型別系統:
- 一組基本型別構成的“基本型別集合”;
- “基本型別集合”上定義的一系列組合、運算、轉換方法。
型別系統包括基礎型別(byte、int、bool、float等);複合型別(陣列、結構體、指標等);可以指向任何物件的型別(Any型別,類似Java的Object型別);值語義和引用語義;面向物件型別;介面。Go大多數型別為值語義,可以給任何型別新增方法(包括內建型別,不包括指標型別)。Any型別是空介面即interface{}。
1.方法
1、為型別新增方法[類方法宣告],方法即為有接收者的函式
func (物件名 物件型別) 函式名(引數列表) (返回值列表)
可隨時為某個物件新增方法即為某個方法新增歸屬物件(receiver),以方法為中心
在Go語言中沒有隱藏的this指標,即顯示傳遞,形參即為this,例如以下的形參為a。
type Integer int func (a Integer) Less(b Integer) bool{ //表示a這個物件定義了Less這個方法,a可以為任意型別 return a<b } //型別基於值傳遞,如果要修改值需要傳遞指標 func (a *Integer) Add(b Integer){ *a+=b //通過指標傳遞來改變值 } |
2.值語義和引用語義
值型別:b的修改並不會影響a的值
引用型別:b的修改會影響a的值
Go大多型別為值語義,包括基本型別:byte,int,string等;複合型別:陣列,結構體(struct),指標等
//2、值語義和引用語義 b=a b.Modify() //值型別 var a=[ 3 ] int { 1 , 2 , 3 } b:=a b[ 1 ]++ fmt.Println(a,b) //a=[1,2,3] b=[1,3,3] //引用型別 a:=[ 3 ] int { 1 , 2 , 3 } b:=&a //b指向a,即為a的地址,對b指向的值改變實際上就是對a的改變(陣列本身就是一種地址指向) b[ 1 ]++ fmt.Println(a,*b) //a=[1,3,3] b=[1,3,3] //*b,取地址指向的值 |
3.結構體
3、結構體[類屬性的宣告]
struct的功能類似Java的class,可實現巢狀組合(類似繼承的功能)
struct實際上就是一種複合型別,只是對類中的屬性進行定義賦值,並沒有對方法進行定義,方法可以隨時定義繫結到該類的物件上,更具靈活性。可利用巢狀組合來實現類似繼承的功能避免程式碼重複。
type Rect struct{ //定義矩形類 x,y float64 //型別只包含屬性,並沒有方法 width,height float64 } func (r *Rect) Area() float64{ //為Rect型別繫結Area的方法,*Rect為指標引用可以修改傳入引數的值 return r.width*r.height //方法歸屬於型別,不歸屬於具體的物件,宣告該型別的物件即可呼叫該型別的方法 } |
(二)初始化[例項化物件]
資料初始化的內建函式new()與make(),二者都是用來分配空間。區別如下:
- new()
- func new(Type) *Type
- 內建函式
new
分配空間。傳遞給new
函式的是一個型別,不是一個值。返回值是指向這個新分配的零值的指標
- make()
- func make(Type, size IntegerType) Type
- 內建函式
make
分配並且初始化 一個 slice, 或者 map 或者 chan 物件。 並且只能是這三種物件。 和new
一樣,第一個引數是 型別,不是一個值。 但是make
的返回值就是這個型別(即使一個引用型別),而不是指標。 具體的返回值,依賴具體傳入的型別。
//建立例項 rect1:= new (Rect) //new一個物件 rect2:=&Rect{} //為賦值預設值,bool預設值為false,int預設為零值0,string預設為空字串 rect3:=&Rect{ 0 , 0 , 100 , 200 } //取地址並賦值,按宣告的變數順序依次賦值 rect4:=&Rect{width: 100 ,height: 200 } //按變數名賦值不按順序賦值 //建構函式:沒有構造引數的概念,通常由全域性的建立函式NewXXX來實現建構函式的功能 func NewRect(x,y,width,height float64) *Rect{ return &Rect{x,y,width,height} //利用指標來改變傳入引數的值達到類似構造引數的效果 } //方法的過載,Go不支援方法的過載(函式同名,引數不同) //v …interface{}表示引數不定的意思,其中v是slice型別,及宣告不定引數,可以傳入任意引數,實現類似方法的過載 func (poem *Poem) recite(v ... interface {}) { fmt.Println(v) } |
(三)匿名組合[繼承]
組合,即方法代理,例如A包含B,即A通過訊息傳遞的形式代理了B的方法,而不需要重複寫B的方法。
繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下對這些功能進行擴充套件。繼承主要為了程式碼複用,繼承也可以擴充套件已存在的程式碼模組(類)。
嚴格來講,繼承是“a kind of ”,即子類是父類的一種,例如student是person的一種;組合是“a part of”,即父類是子類中的一部分,例如眼睛是頭部的一部分。
//1、匿名組合的方式實現了類似Java繼承的功能,可以實現多繼承 type Base struct{ Name string } func (base *Base) Foo(){...} //Base的Foo()方法 func (base *Base) Bar(){...} //Base的Bar()方法 type Foo struct{ Base //通過組合的方式聲明瞭基類,即繼承了基類 ... } func (foo *Foo) Bar(){ foo.Base.Bar() //並改寫了基類的方法,該方法實現時先呼叫基類的Bar()方法 ... //如果沒有改寫即為繼承,呼叫foo.Foo()和呼叫foo.Base.Foo()的作用的一樣的 } //修改記憶體佈局 type Foo struct{ ... //其他成員資訊 Base } //以指標方式組合 type Foo struct{ *Base //以指標方式派生,建立Foo例項時,需要外部提供一個Base類例項的指標 ... } //名字衝突問題,組合內外如果出現名字重複問題,只會訪問到最外層,內層會被隱藏,不會報錯,即類似java中方法覆蓋/重寫。 type X struct{ Name string } type Y struct{ X //Y.X.Name會被隱藏,內層會被隱藏 Name string //只會訪問到Y.Name,只會呼叫外層屬性 } |
(四)可見性[封裝]
封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏。
封裝的本質或目的其實程式對資訊(資料)的控制力。封裝分為兩部分:該隱藏的隱藏,該暴露的暴露。封裝可以隱藏實現細節,使得程式碼模組化。
Go中用大寫字母開頭來表示public,可以包外訪問;小寫字母開頭來表示private,只能包內訪問;訪問性是包級別非型別級別
如果可訪問性是型別一致的,可以加friend關鍵字表示朋友關係可互相訪問彼此的私有成員(屬性和方法)
type Rect struct{ X,Y float64 Width,Height float64 //字母大寫開頭表示該屬性可以由包外訪問到 } func (r *Rect) area() float64{ //字母小寫開頭表示該方法只能包內呼叫 return r.Width*r.Height } |
(五)介面[多型]
多型性(polymorphisn)是允許你將父物件設定成為和一個或更多的他的子物件相等的技術,賦值之後,父物件就可以根據當前賦值給它的子物件的特性以不同的方式運作。
簡而言之,就是允許將子類型別的指標賦值給父類型別的指標。
即一個引用變數倒底會指向哪個類的例項物件,該引用變數發出的方法呼叫到底是哪個類中實現的方法,必須在由程式執行期間才能決定。不修改程式程式碼就可以改變程式執行時所繫結的具體程式碼,讓程式可以選擇多個執行狀態,這就是多型性。多型分為編譯時多型(靜態多型)和執行時多型(動態多型),編譯時多型一般通過方法過載實現,執行時多型一般通過方法重寫實現。
5.1介面概念
介面即一組方法的集合,定義了物件的一組行為,方法包含實際的程式碼。換句話說,一個介面就是定義(規範或約束),而方法就是實現,介面的作用應該是將定義與實現分離,降低耦合度。習慣用“er”結尾來命名,例如“Reader”。介面與物件的關係是多對多,即一個物件可以實現多個介面,一個介面也可以被多個物件實現。
介面是Go語言整個型別系統的基石,其他語言的介面是不同元件之間的契約的存在,對契約的實現是強制性的,必須顯式宣告實現了該介面,這類介面稱之為“侵入式介面”。而Go語言的介面是隱式存在,只要實現了該介面的所有函式則代表已經實現了該介面,並不需要顯式的介面宣告。
- 介面的比喻
你的電腦上只有一個USB介面。這個USB介面可以接MP3,數碼相機,攝像頭,滑鼠,鍵盤等。。。所有的上述硬體都可以公用這個介面,有很好的擴充套件性,該USB介面定義了一種規範,只要實現了該規範,就可以將不同的裝置接入電腦,而裝置的改變並不會對電腦本身有什麼影響(低耦合)。
- 面向介面程式設計
介面表示呼叫者和設計者的一種約定,在多人合作開發同一個專案時,事先定義好相互呼叫的介面可以大大提高開發的效率。介面是用類來實現的,實現介面的類必須嚴格按照介面的宣告來實現介面提供的所有功能。有了介面,就可以在不影響現有介面宣告的情況下,修改介面的內部實現,從而使相容性問題最小化。
當其他設計者呼叫了介面後,就不能再隨意更改介面的定義,否則專案開發者事先的約定就失去了意義。但是可以在類中修改相應的程式碼,完成需要改動的內容。
5.2非侵入式介面
非侵入式介面:一個類只需要實現了介面要求的所有函式就表示實現了該介面,並不需要顯式宣告
相關推薦Golang系列(二)之面向物件程式設計面向物件程式設計: 把一組資料結構和處理它們的方法組成物件(object),把相同行為的物件歸納為類(class),通過類的封裝(encapsulation)隱藏內部細節,通過繼承(inheritance)實現類的特化(specialization)[方法的重寫, python快速學習系列(6):面向物件程式設計(OOP)一、面向物件程式設計: 1.比設計模式更重要的是設計原則: 1)面向物件設計的目標: ·可擴充套件:新特性很容易新增到現有系統中,基本不影響系統原有功能 ·可修改:當修改某一部分程式碼時,不會影響到其他不相關的部分 ·可替代:用具有相同介面的程式碼去替換系統中某一部分程式碼時,系統不受影 C++學習(二) C++面向物件程式設計方法概述(1)面向過程與面向物件的比較 面向過程程式設計方法(C語言) 分析出要解決所需要的步驟,然後用函式把各步驟逐個實現,執行時依次呼叫各個函式即可。 程式 = 演算法 + 資料結構 面向物件程式設計方法(C++語言) 把問題分解成各個物件,描述各個物件的 JDBC詳解系列(二)之加載驅動red mar mys ons try path 替換 host man ---[來自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- ??在JDBC詳解系列(一)之流程中 Vue 進階系列(二)之外掛原理及實現Vue進階系列彙總如下,歡迎閱讀,歡迎加群討論(文末)。 Vue 進階系列(一)之響應式原理及實現 Vue 進階系列(二)之外掛原理及實現 使用方法 外掛的詳細使用方法詳情看Vue官網 Vue官網之外掛Plugins 概括出來就是 1、通過Vue.use(MyPlugin)使用, php7新特性(二):面向物件部分1)、PHP 7 支援new class 來例項化一個匿名類這可以用來替代一些"用後即焚"的完整類定義。 2)、Closure::call():將一個閉包函式動態繫結到一個新的物件例項並呼叫執行該函式 3)、use:可以使用一個 use 從同一個 namespace 中匯入類、函 java基礎-初級(二)【面向物件與類】目錄 2、面向物件與類 2.1 面向物件思想 2.2 類與物件 2.3 成員和區域性變數 2.4 匿名物件 2.5 類的訪問許可權修飾符 2.6 static關鍵字-靜態域、靜態 (二)Kotlin 面向物件文章目錄 一、面向物件的概念 二、抽象類與介面 1、介面 2、抽象類 3、抽象類和介面的共性 3、抽象類和介面的區別 三、類的繼承與介面的實現 Golang系列(五)之Golang指標1. 指標的概念 概念 說明 變數 是一種佔位符,用於引用計算機的記憶體地址。可理解為記憶體地址的標籤 指標 表示記憶體地址,表示地址的指向。指標是一個指向另一個變數記憶體地址的值 & 取地址符, 深入JVM系列(二)之GC機制、收集器與GC調優一、回顧JVM記憶體分配 1.1、記憶體分配: 1、物件優先在EDEN分配 2、大物件直接進入老年代 3、長期存活的物件將進入老年代 4、適齡物件也可能進入老年代:動態物件年齡判斷 動態物件年齡判斷: 虛擬機器並不總是要求物件的年齡必須達到MaxTenuring tkinter學習系列(二)之窗口的設置code 註意 figure con loop 基本 icon 方法 mos 目錄 (一)窗體的最小框架 1.說明: 2.源代碼: 3.實現效果: [Java]“語法糖”系列(二)之Lambda表示式/匿名函式(Lambda Expression)>什麼是Lambda表示式 簡短的說,Lambda表示式是一種用於取代匿名類,把函式行為表述為函數語言程式設計風格的一種匿名函式。 匿名類大家自然熟悉,上面那句話提到了“函式行為”,那麼什麼是函式行為? >函式行為 假設有這樣一個應用場 自己用的C#基礎學習筆記(二)——C#面向物件(2)1 第十一天 1.1 string stringbuffer stringbulider 1.三者在執行速度方面的比較:StringBuilder > StringBuffer > String 2.String <(StringBuffer,Str tkinter內嵌Matplotlib系列(二)之函數曲線繪制erro labels imp sed 窗體 ret 啟動 背景 res 目錄 目錄 前言 (一)對matplotlib畫布的封裝: (二)思路分析: 1. Golang系列(一)之基礎篇一、初識Go語言(一)概述一個在語言層面實現了併發機制的類C通用型程式語言。(二)Go關鍵字(25個)類別關鍵字說明程式宣告package,import包的宣告和匯入宣告與定義var,const變數和常量的宣告type用於定義型別複合資料型別struct定義結構體,類似java中的classinterface 編寫高質量的Python代碼系列(二)之函數可復用 可選 第十四 減少 文檔字符串 str 特殊 作用 作用域 Python中的函數具備多種特性,這可以簡化編程工作。Python函數的某些性質與其他編程語言中的函數相似,但也有性質是Python獨有的。本節將介紹如何用函數來表達億圖、提升可復用程度,並減少Bug Java課堂筆記(二):面向物件幾乎每一本介紹Java語言的書中都會提到“面向物件”的這個概念,然而博主初學Java時看到這方面的內容一般都是草草地看一看,甚至是直接略過。原因很簡單:考試基本不考,而且初學階段寫程式碼也很少用上。但事實上面向物件時Java中一個 設計模式(二):面向物件及其特性分析# 面向物件 > 根據大綱,首先我們來學習一種程式碼設計與編寫的風格,即面向物件。 ## 面向物件程式設計和麵向物件程式語言 - 面向物件程式設計是一種程式設計正規化,通俗來說,就是將 **程式碼的組織單元改成類和物件**,並將 **封裝、繼承、抽象、多型** 作為程式碼設計和編寫的基石。 - 聽課筆記---程式設計與演算法(三)C++面向物件程式設計(郭偉老師)---第三週Week3 目錄 this 指標 靜態成員函式和靜態成員變數 成員物件和封閉類 常量物件和常量函式 友元 內容與思考 this 指標 靜態成員函式和靜態成員變數 歷史由來 C++原來沒有編譯器,可以 Java面向物件與多執行緒綜合實驗(二)之 異常處理理解異常的基本概念;瞭解Java異常的層次結構;熟悉並掌握Java異常的捕獲處理方法。 (1)閱讀Java™ Platform, Standard Edition 8 API Specification文件,瞭解後續程式設計中將要處理的IOException及其子類FileNotFoundE |