Go 面向對象三大特性

#### Go 中面向對象的三大特性
上週由於有一些事情,停更了; 停更的這段時間,花了點時間作了一個小項目(https://github.com/yioMe/node_wx_alipay_personalPay)
原項目由node.js 寫的,根據文檔用Go 重寫了(Gin + MySQL) ;
1. 沒有了繁瑣的node安裝;
2. 沒有 DB 遷移;
3. 支付成功回調優化;
4. 性能提高;
5. 修復了上傳二維碼不能識別的問題;
不過只重寫了一小部分功能,應對平常我的支付不成問題,若有須要瞭解的朋友,私聊一同交流學習;
---
言歸正傳,Go 中的面向對象的特性與傳統的OOP 語言不一樣,咱們來一一學習瞭解;
###### 封裝
封裝就是把抽象的字段的對字段的操做封裝在一塊兒,數據被保護在內部,程序中的其它包只能經過被受權的操做才能對
字段操做;
封裝的好處:
1. 隱藏實現的細節;
2. 能夠對數據進行驗證,保證數據的安全合理;
---
封裝實現的步驟:
1. 將結構體,字段的首字母小寫,不能被導出,其它包不能使用,相似JAVA 的private ;
2. 在結構體所在的包提供一下工廠模式的函數,首寫字母大寫,相似構造函數;
3. 提供一個首字母大寫的Set 方法,用於對屬性的判斷並賦值
4. 提供一個首字母大寫的Get 方法,用於獲取屬性的值;
5. 在Go 中沒有特別強調封裝,因此有其它編程語言的朋友,不須要用其它的語法特性來學習Go, 每種編程語言都有各自的特色;
package model

import "fmt"

type student struct {
   Name string
   age int  // 其它的包不能直接訪問
   score float64 // 其它的包不能直接訪問
}

// 工廠方法,至關於構造函數
func NewStudent(name string) *student{
   return &student{
      Name:name,
   }
}
// 爲了訪問和更改結構體的屬性,編寫一對GetXxx/SetXxx 的方法
// this 只是接收類型的名稱, 能夠命名爲任意合法的標識符
func (this *student) GetAge() int {
   return this.age
}
func (this *student) SetAge(age int){
   // 能夠在Set 方法裏對數據進行校驗
   if age < 0 || age > 100 {
      fmt.Println("age is wrong")
      return
   }
   this.age = age
}
func (this *student) GetScore() float64{
   return this.score
}
func (this *student) SetScore(score float64) {
   if score < 0 || score > 100 {
      fmt.Println("score is wrong")
      return
   }
   this.score = score
}

  

 
package main

import (
   "fmt"
   "personalPayment/model"
)

func main(){
   p := model.NewStudent("jack")
   p.SetAge(20)
   p.SetScore(200)
   fmt.Println(*p)
   fmt.Println(p.Name,"age=",p.GetAge(),"score=",p.GetScore())
}

  


---
###### 繼承
1. 繼承能夠解決代碼的複用問題
2. 當多個結構體有相同的屬性和方法時,能夠從這些結構體中抽象一下基礎的結構體,在該結構體中定義相同的屬性和方法;
3. Go 中實現繼承是經過結構體匿名嵌套來實現;
基本語法:
type Person struct {
Name string
Age int
}

type Student struct {
Person // 嵌套的結構體,實現繼承
Score float64
}
案例:
package model

import "fmt"
type person struct {
   Name string
   age int
}
type student struct {
   person
   score float64 // 其它的包不能直接訪問
}
type teacher struct {
   person
   class string
}

// 學生的工廠方法,至關於構造函數
func NewStudent(name string) *student{
   return &student{ person:person{
      Name:name,
   },
   }
   }
// 老師的工廠方法
func NewTeacher(name string) *teacher{
   return &teacher{person:person{
      Name:name,
   }}
}
// 基礎結構的公衆方法
func (this *person) GetAge() int {
   return this.age
}
func (this *person) SetAge(age int){
   // 能夠在Set 方法裏對數據進行校驗
   if age < 0 || age > 100 {
      fmt.Println("age is wrong")
      return
   }
   this.age = age
}
// 學生的方法
func (this *student) GetScore() float64{
   return this.score
}
func (this *student) SetScore(score float64) {
   if score < 0 || score > 100 {
      fmt.Println("score is wrong")
      return
   }
   this.score = score
}
// 老師的方法
func (this *teacher) GetClass() string {
   return this.class
}
func (this *teacher) SetClass(class string){
   this.class = class
}

  

 
package main

import (
   "fmt"
   "personalPayment/model"
)

func main(){
   s := model.NewStudent("jack")
   // 調用公用的結構體方法
   s.SetAge(20)
   // 調用本身的方法
   s.SetScore(100)
   fmt.Println(s.Name,s.GetAge(),s.GetScore())
   t := model.NewTeacher("tom")
   // 調用公用的結構體方法
   t.SetAge(40)
   // 調用本身的方法
   t.SetClass("English")
   fmt.Println(t.Name,t.GetAge(),t.GetClass())
}

  


繼承的使用和注意事項
1. 結構體可使用嵌套匿名的結構體中的全部的屬性和方法,不論大寫與小寫
2. 結構體中匿名結構體的字段和方法能夠簡化;
3. 當結構體和匿名結構體有相同的屬性和方法時,編譯器採用就近原則,若是須要訪問匿名結構體中的字段
和方法須要經過匿名結構體的名稱來區分;
4. 若是一個結構體嵌套了一個有名稱的結構體,這種模式稱爲組合,在訪問組合的結構體或方法時須要加上結構體的名字;
package main

import (
   "fmt"
)

type person struct {
   Name string
   Age int
   skill string
}
type student struct {
   person
   score float64
}
func (p *person) Say(){
   fmt.Println("I am a person")
}
func (p *person) Do(){
   fmt.Println("I am doing something")
}

type A struct {
   Name string
}
type B struct {
   A
   Name string
}
type C struct {
   Name string
}
type D struct {
   c C
   Age int
}
func main(){
   s := &student{}
   s.person.Say()
   s.person.Do()
   s.person.Name = "jack"
   s.person.Age = 20
   s.person.skill = "speak"
   fmt.Println(*s)
   // 對匿名結構體中的屬性方法能夠簡化爲
   s.Say()
   s.Do()
   s.Name = "jack2"
   s.Age = 21
   s.skill = "laugh"
   fmt.Println(*s)
   // 若是結構體和匿名結構體中有相同的屬性或方法,編譯器將採用就近原則,
   // 若是須要訪問匿名結構體的屬性和方法須要經過匿名結構體的名稱
   a := B{
      A: A{
         Name:"aaa",
      },
      Name:"bbb",
   }
   fmt.Println(a.Name) // bbb
   fmt.Println(a.A.Name) // aaa
   // 對於組合,在訪問繼承結構體的方法或屬性時須要加上結構體的名稱 
   d := D{
      c:C{Name:"ccc"},
      Age:20,
   }
   fmt.Println(d.Age) // 本身的屬性
   fmt.Println(d.c.Name) // 訪問繼承的屬性
}

  我的微信公衆號上有最新文章,歡迎關注一同交流學習node

相關文章
相關標籤/搜索