1. 程式人生 > >Golang系列(二)之面向物件程式設計

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 intfunc (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=ab.Modify()//值型別var a=[3]int{1,2,3}b:=ab[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()
  1. func new(Type) *Type
  2. 內建函式 new 分配空間。傳遞給new 函式的是一個型別,不是一個值。返回值是指向這個新分配的零值的指標
  • make()
  1. func make(Type, size IntegerType) Type
  2. 內建函式 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