Hike News
Hike News

Golang物件導向初識-day17-結構體方法2

方法

  • 結構體(struct)可認為是其他語言的類(class),亦可定義適用於此結構體的方法
  • Golang中的方法是作用在特定類型的變量
  • 方法仍是透過方法名的大小寫來決定外部是否能調用,小寫的方法名為私有方法

定義

1
2
3
4
5
6
7
8
func (適用類型) 方法名 (參數列表) (返回值){
方法內容
}

//例子:
func (self *Student) print_info (Name string, Age int, Score float64)int{

}
  • 適用類型決定此方法適用於何種結構體類型
  • self為適用類型的實例,可自訂義為其他名字,方法會作用於 結構體或是類型本身
  • 與定義函數沒有區別,最大的差異為適用此函數的類型需正確

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import(
"math/rand"
"fmt"
)

type Student struct{
Name string
Age int
score float64
ID int
}

//接收指針類型的實例化對象
func (self *Student)Stu_init(name string, age int, input_score float64,)int{
self.Name = name
self.Age = age
self.score = input_score
self.ID = rand.Intn(1000)
fmt.Println(*self)
return self.ID
}

func main(){
var Tom Student = Student{}

//調用方法 實例化物件.方法即可調用
Tom_ID := Tom.Stu_init("Tom",20,80)

fmt.Println(Tom_ID)
}

result

1
2
{Tom 20 80 81}
81

tips

  • 實例化對象最好在定義方法時傳入指針類型,否則再調用函數的時候,實例化的對象會因為是值類型,而無法連續操作

使用值類型傳參

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import(
"math/rand"
"fmt"
)

type Student struct{
Name string
Age int
score float64
ID int
}

func (self Student)Stu_init(name string, age int, input_score float64,)int{
self.Name = name
self.Age = age
self.score = input_score
self.ID = rand.Intn(1000)
fmt.Println(self)
return self.ID
}

func (self Student)get()Student{
return self
}

func main(){
var Tom Student = Student{}
Tom_ID := Tom.Stu_init("Tom",20,80)
fmt.Println(Tom_ID)
fmt.Println(Tom.get())
}
result
1
2
3
{Tom 20 80 81}
81
{ 0 0 0}

使用指針傳參

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import(
"math/rand"
"fmt"
)

type Student struct{
Name string
Age int
score float64
ID int
}

func (self *Student)Stu_init(name string, age int, input_score float64,)int{
self.Name = name
self.Age = age
self.score = input_score
self.ID = rand.Intn(1000)
fmt.Println(*self)
return self.ID
}

func (self *Student)get()*Student{
return self
}

func main(){
var Tom Student = Student{}
Tom_ID := Tom.Stu_init("Tom",20,80)
fmt.Println(Tom_ID)
fmt.Println(*Tom.get())
}
  • 因方法的適用類型為指針類型,所以在調用函數時應(&Tom).Stu_init()或是(&Tom).get())調用
  • 但是golang內部做了簡化,會自動判斷 前面的對象為何種類型傳入值類型或是指針類型
  1. 若適用方法為self StudentTom.get()傳入為值類型
  2. 若適用方法為self *StudentTom.get()默認就是(&Tom).get()傳入指針類型
result
1
2
3
{Tom 20 80 81}
81
{Tom 20 80 81}

繼承與組合 (結構體之間的嵌套)

  • 如果一個struct嵌套了另一個匿名結構體,那麼這個結構體可以直接訪問匿名結構體的方法,從而實現了繼承
    (可參考Golang物件導向初識-day16-結構體方法1 章節)

  • 如果有一個struct嵌套了另一個有名結構體,那麼這個模式就叫做組合

    example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    package main

    import(
    "math/rand"
    "fmt"
    )

    // Classroom結構體 繼承了Student匿名結構體 及 組合了Tch結構體(Teacher類型)
    type Classroom struct{
    Student
    Tch Teacher
    RoomNumber int
    }

    type Teacher struct {
    Name string
    Age int
    Major string
    }

    func (self *Teacher) GetInfo(){
    fmt.Println("Teacher Name:",self.Name," age:",self.Age," Major",self.Major)
    }


    type Student struct{
    Name string
    Age int
    score float64
    ID int
    }

    func (self *Student)Stu_init(name string, age int, input_score float64,)int{
    self.Name = name
    self.Age = age
    self.score = input_score
    self.ID = rand.Intn(1000)
    fmt.Println(*self)
    return self.ID
    }

    func (self *Student)get()*Student{
    return self
    }

    func main(){
    var One Classroom

    // Classroom 結構體調用了Student匿名字段中的方法
    fmt.Println("John's ID=",One.Stu_init("John",18,60))

    // Classroom 子類調用了父類Teacher組合的字段
    One.Tch.Name = "Teacher Chang"
    One.Tch.Major = "Chemistry"
    One.Tch.Age = 40

    // Classroom 子類調用了父類Teacher組合的方法
    One.Tch.GetInfo()
    }
  • 一個子結構體嵌套了一個父匿名結構體,則子結構體實現了父結構體中所有的屬性及方法
  • 亦可稱匿名字段是一種特殊的組合
  • 一個子結構體嵌套了一個父有名結構體組合,則子結構體實現了父結構體中所有的屬性及方法
  • 組合調用方法都必須加字段名

result

1
2
3
{John 18 60 81}
John's ID= 81
Teacher Name: Teacher Chang age: 40 Major Chemistry

多重繼承

  • 一個struct嵌套了多個匿名結構體,此結構體可直接訪問多個匿名結構體的方法,就實現了多重繼承
  • 要是兩個匿名結構體中有相同字段,且要訪問此字段時
    必須透過 實例化變量.匿名結構體類型.字段訪問

  • 要是兩個匿名結構體之間皆為不同字段,要訪問字段時
    直接透過 實例化變量.字段訪問即可