Golang繼承中字段及方法的測試

Golang採用嵌入字段來實現繼承,由於實現上存在多種可能,這裏進行測試,看看Golang的設計思路。

待考察的問題包括:
     嵌入的是結構,還是指針?
     嵌入部分是匿名字段,還是命名字段?
     方法是傳值,還是傳指針?

最終結論:
     可以嵌入字段,也可以嵌入指針,其特性吻合慣性思維
     無論字段是否指針,無論方法的接收者是否指針,在字段引用時都不區分指針

以下是測試過程

     一共4組不同情形的測試
          結構中有另一個結構,這是最簡單的情形
          結構中有一個匿名結構,測試用類型代替字段名,或直接引用
          結構中有指針指向另一個結構
          結構中有匿名指針指向另一個結構

     每組測3個項目
          繼承後的引用
          傳值方法的繼承
          傳指針方法的繼承

     故一共12個測試



第1組測試
     結構中有另一個結構,這是最簡單的情形


package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    person Person // 有另一個字段
    school string
}


func main() {
    anna := new(Student)
    anna.person.name = "Anna"
    anna.person.tel = "12345678"
    //anna.school = "mit"
 
    fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
 
}


第1.1組測試
     結構中有另一個結構,這是最簡單的情形
     測試這種情況下方法的繼承

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    person Person // 有另一個字段
    school string
}

//在person上面定義了一個傳值的method
func (p Person) Hello() {
    fmt.Printf("My name is %s, and my tel number is %s\n", p.name, p.tel)
}
func main() {
    anna := new(Student)
    anna.person.name = "Anna"
    anna.person.tel = "2345678"
    //anna.school = "mit"
     
      // anna.Hello() // 這是不行的,非匿名字段不能直接引用
      anna.person.Hello()
     
    //fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}

結論:
     如果字段沒有匿名,則相當於中間隔了一層,不能跨越去引用

第1.2組測試
     結構中有另一個結構,這是最簡單的情形
     測試這種情況下方法的繼承
     但是定義傳指針的method

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    person Person // 有另一個字段
    school string
}

//在person上面定義了一個傳指針的method
func (p * Person) Hello() {
    fmt.Printf( "My name is %s, and my tel number is %s\n", p.name, p.tel)
}
func main() {
    anna := new(Student)
    anna.person.name = "Anna"
    anna.person.tel = "345678"
    //anna.school = "mit"
    
       // anna.Hello() // 這是不行的,非匿名字段不能直接引用
      anna.person.Hello()
    
    //fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}

結論:
     沒有問題,method傳值或傳指針沒有區別

第2組測試
     結構中有一個匿名結構,測試用類型代替字段名,或直接引用

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    Person // 有一個匿名字段
    school string
}


func main() {
    anna := new(Student)
    anna.Person.name = "Anna" // 用類型代替字段名
    anna.tel = "123456789" // 或者直接引用
    //anna.school = "mit"
 
    fmt.Printf( "My name is %s, and my tel number is %s\n", anna.Person.name, anna.tel)
 
}



第2.1組測試
     結構中有一個匿名結構
     測試這種情況下方法的繼承


package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    Person // 有另一個字段
    school string
}

//在person上面定義了一個傳值的method
func (p Person) Hello() {
    fmt.Printf("My name is %s, and my tel number is %s\n", p.name, p.tel)
}
func main() {
    anna := new(Student)
    anna.Person.name = "Anna"
    anna.tel = "2345"
    //anna.school = "mit"
     
      anna.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
     
    //fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}

結論:匿名字段,相當於匿名結構直接嵌入,在同一層面

第2.2組測試
     結構中有一個匿名結構
     測試這種情況下方法的繼承
     但是定義傳指針的method

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    Person // 有另一個字段
    school string
}

//在person上面定義了一個傳指針的method
func (p * Person) Hello() {
    fmt.Printf( "My name is %s, and my tel number is %s\n", p.name, p.tel)
}
func main() {
    anna := new(Student)
    anna.Person.name = "Anna"
    anna.tel = "345"
    //anna.school = "mit"
    
      anna.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
    
    //fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}

結論:
     傳指針無影響

第3組測試
     結構中有指針指向另一個結構

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    person * Person // 指針指向一個字段
    school string
}


func main() {
    anna := new(Student)
    anna.person = new(Person) // 必須,否則panic
    anna.person.name = "Anna"
    anna.person.age = 22
    anna.person.tel = "12345"
    anna.school = "mit"
  
    fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
  
}


第3.1組測試
     結構中有指針指向另一個結構
     測試方法的繼承

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    person * Person // 指針指向一個字段
    school string
}

//在person上面定義了一個傳值的method
func (p Person) Hello() {
    fmt.Printf("My name is %s, and my tel number is %s\n", p.name, p.tel)
}

func main() {
    anna := new(Student)
    anna.person = new(Person)
    anna.person.name = "Anna"
    anna.person.tel = "234567"
     
      anna.person.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
     
}

結論:
     非常正常的使用

第3.2組測試
     結構中有指針指向另一個結構
     測試方法的繼承
     但是定義傳指針的method

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    person * Person // 指針指向一個字段
    school string
}

//在person上面定義了一個傳指針的method
func (p * Person) Hello() {
    fmt.Printf( "My name is %s, and my tel number is %s\n", p.name, p.tel)
}

func main() {
    anna := new(Student)
    anna.person = new(Person)
    anna.person.name = "Anna"
    anna.person.tel = "345678"
    
      anna.person.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
    
}

結論:
     指針無影響

第4組測試
     結構中有匿名指針指向另一個結構

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    * Person // 匿名指針指向一個字段
    school string
}


func main() {
    anna := new(Student)
    anna.Person = new(Person)
    anna.Person.name = "Anna"
    //anna.Person.age = 22
    anna.tel = "123"
    //anna.school = "mit"
 
    fmt.Printf( "My name is %s, and my tel number is %s\n", anna.Person.name, anna.tel)
 
}

結論:
     anna.Person = new(Person) 居然也行
     匿名相當於直接嵌入,在同一層面
     Golang似乎是儘量識別,如果有字段名,包括指針,則必須用字段名,如果是匿名,則可用匿名字段的類型
  
第4.1組測試
     結構中有匿名指針指向另一個結構
     測試方法的繼承

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    * Person // 匿名指針指向一個字段
    school string
}


//在person上面定義了一個傳值的method
func (p Person) Hello() {
    fmt.Printf("My name is %s, and my tel number is %s\n", p.name, p.tel)
}

func main() {
    anna := new(Student)
    anna.Person = new(Person)
    anna.Person.name = "Anna"
    anna.tel = "23456789"

     
      anna.Person.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
      anna.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
}

結論
     在同一層面,當然加上匿名指針也可

第4.2組測試
     結構中有匿名指針指向另一個結構
     測試方法的繼承
     但是定義傳指針的method

package main
import "fmt"

type Person struct {
    name string
    age int
    tel string
}

type Student struct {
    * Person // 匿名指針指向一個字段
    school string
}


//在person上面定義了一個傳指針的method
func (p * Person) Hello() {
    fmt.Printf( "My name is %s, and my tel number is %s\n", p.name, p.tel)
}

func main() {
    anna := new(Student)
    anna.Person = new(Person)
    anna.Person.name = "Anna"
    anna.tel = "34"

    
      anna.Person.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
      anna.Hello() // 匿名字段,相當於匿名結構直接嵌入,在同一層面
}

結論:
     一樣使用



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章