@@ -1,58 +0,0 @@ 14.匿名组合 | 凤凰涅槃进阶之路

14.匿名组合

Abel sun2023年1月6日约 960 字大约 3 分钟

14.匿名组合

对于面向对象变成的支持,Go语言设计的非常简洁且优雅。因为,Go语言并没有沿袭传统面向对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继承),虚函数,构造函数和析构函数,隐藏的this指针等。

传统面向对象核心概念可如图了解:

m_2ab287133a302b022f5eaf17ba39d3cb_r

尽管Go语言中没有封装,继承,多态这些概念,但同样通过别的方式实现了这些特性:

  • 封装:通过方法实现
  • 继承:通过匿名字段实现
  • 多态:通过接口实现

一般情况下,定义结构体的时候是字段名与其类型一一对应,实际上Go支持只提供类型,而不写字段名的方式,也就是匿名字段,也称为嵌入字段。

当匿名字段也是一个结构体的时候,那么这个结构体所拥有的全部字段都被隐式地引入了当前定义的这个结构体。

1,匿名字段

package main

import "fmt"

type Person struct {
 name string
 sex  byte
 age  int
}

type Student struct {
 //内容重叠的,可以直接引用,只有类型,没有名字,就是匿名字段
 //这样Student就会继承Person这个结构体里边的成员了
 Person
 id   int
 addr string
}

func main() {

}

2,匿名字段初始化

package main

import "fmt"

type Person struct {
 name string
 sex  byte
 age  int
}

type Student struct {
 //内容重叠的,可以直接引用,只有类型,没有名字,就是匿名字段
 //这样Student就会继承Person这个结构体里边的成员了
 Person
 id   int
 addr string
}

func main() {
 //顺序初始化
 var s1 = Student{Person{"yoyo", 'm', 18}, 1, "hangzhou"}
 fmt.Println("s1 = ", s1)

 //自动推导类型
 s2 := Student{Person{"yoyo", 'm', 18}, 1, "hangzhou"}
 //fmt.Println("s2 = ", s2)
 //%+v显示详细信息
 fmt.Printf("s2 = %+v\n", s2)

 //指定成员初始化,没有初始化的默认为0
 s3 := Student{addr: "hangzhou"}
 fmt.Printf("s3 = %+v\n", s3)

 s4 := Student{Person: Person{age: 18}, addr: "hangzhou"}
 fmt.Printf("s4 = %+v\n", s4)

 //s5 := Student{age: 18, addr: "hangzhou"} //err
}

3,成员的操作

package main

import "fmt"

type Person struct {
 name string
 sex  byte
 age  int
}

type Student struct {
 Person
 id   int
 addr string
}

func main() {

 s1 := Student{Person{"yoyo", 'm', 18}, 1, "hangzhou"}
 fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)
 //修改某个成员的值
 s1.name = "eryajf"
 s1.age = 22
 s1.id = 5
 fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)

 //修改Person里边的值
 s1.Person = Person{"long", 'b', 20}
 fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)
}

4,同名字段

其规则与前边的同名变量时一致的。

package main

import "fmt"

type Person struct {
 name string
 sex  byte
 age  int
}

type Student struct {
 Person
 id   int
 addr string
 name string
}

func main() {
 //定义一个变量
 var s Student
 //如果定义的结构体引用的匿名字段有重名字段,那么在字段赋值的时候
 //默认规则为就近原则,如果就近没有,再往外层匹配
 s.name = "erya" //这个name是给Student赋值
 s.sex = 'm'
 s.age = 18
 s.addr = "hangzhou"
 fmt.Printf("s = %+v\n", s)

 //如果要给Person里边的name字段赋值,则需要显式调用
 s.Person.name = "long"
 fmt.Printf("s = %+v\n", s)

}

5,非结构体匿名字段

package main

import "fmt"

type mystr string //自定义类型,相当于别名

type Person struct {
 name string
 sex  byte
 age  int
}

type Student struct {
 Person //结构体类型匿名字段
 int    //基础类型匿名字段
 mystr
}

func main() {
 s := Student{Person{"yoyo", 'm', 18}, 666, "hangzhou"}
 fmt.Printf("s = %+v\n", s)

 s.Person = Person{"erya", 'm', 22}
 fmt.Println(s.Person, s.int, s.mystr)

}

6,结构体指针类型匿名字段

package main

import "fmt"

type Person struct {
 name string
 sex  byte
 age  int
}

type Student struct {
 *Person //指针类型
 id      int
 addr    string
}

func main() {

 s1 := Student{&Person{"yoyo", 'm', 18}, 1, "hangzhou"}
 fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)

 //通过new操作
 var s2 Student
 s2.Person = new(Person)
 s2.name = "eryajf"
 s2.age = 22
 s2.id = 5
 fmt.Println(s2.name, s2.sex, s2.age, s2.id, s2.addr)

}
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.9.1