作者:连向明 | 来源:互联网 | 2023-08-14 09:04
Golang中匿名结构体和匿名字段,结构体嵌套,模拟继承性学习这篇文章也是结构体的学习,不过,如果没有结构体struct基础的话,推荐先看Golang学习——结构体struct(一
Golang中匿名结构体和匿名字段,结构体嵌套,模拟继承性学习
这篇文章也是结构体的学习,不过,如果没有结构体struct
基础的话,推荐先看Golang学习——结构体struct(一)。
今天主要记录 匿名结构体和匿名字段,结构体嵌套,模拟继承性。
一.匿名结构体和匿名字段
1.匿名结构体
匿名结构体:即没有名字的结构体,在创建匿名结构体时,同时初始化结构体。
实例:
s2 := struct {
name string
age int
}{}
初始化时必须的, 不然会编译报错。实例中,我未具体初始化,使用了默认值。通常,这个语法在实际开发中使用较少,作为了解即可
2.匿名字段
匿名字段:一个结构体的字段没有字段名
我们定义一个Worker结构体,有两个匿名字段,:
type Worker struct {
string
int
}
匿名字段,默认使用数据类型作为名字,那么匿名字段的类型就不能重复,否则会冲突。
通过.
操作正常访问字段,如下:
bob := Worker{"Bob", 22}
fmt.Println(bob)
fmt.Println(bob.string)
fmt.Println(bob.int)
输出:
{Bob 22}
Bob
22
在实际开发中几乎没有人会这么写的,但是我们仍然有必要了解一下,为模拟继承性打好基础。
二.结构体嵌套
结构体嵌套:一个结构体可能包含一个字段,而这个字段反过来就是一个结构体,这种结构被称为嵌套结构。
类似Java中的对象的包含关系 has a
1.实例
定义图书, 学生结构体。其中,学生结构体嵌套了图书结构体
type Book struct {
bookName string
price float64
}
type Student struct {
name string
age int
book Book
}
初始化结构体:
book1 := Book{
bookName: "三国演义",
price: 56.5,
}
student1 := Student{
name: "Tom",
age: 20,
book: book1,
}
fmt.Println("student1 结构体内容:", student1)
fmt.Printf("访问 book1 中的字段,书名:%s,价格:%.2f\n", student1.book.bookName, student1.book.price)
输出:
student1 结构体内容: {Tom 20 {三国演义 56.5}}
访问 book1 中的字段,书名:三国演义,价格:56.50
外部结构体对象(student1)访问内部结构体对象(book1)中的字段时,不能直接student1.bookName
,这是不允许的, 因为两个结构体之间的关系是包含关系,二者的字段是相互独立的。
那如果就是想 student1.bookName
来获取图书名称呢?这就涉及的结构体的继承性了。
三.结构体模拟继承性
在学习了前两小节后,可以顺利的学习Golang中的继承,因为前两小节是学习继承的知识铺垫。
其实Golang并不是纯粹的面向对象的编程语言,但也可以实现继承关系,类似:
是一种 is a
的关系。
1.实例
Golang中通过嵌套匿名结构体来实现继承,具体是什么样的呢?我们实例操作一下:
type Person struct {
name string
age int
}
type Student struct {
Person
school string
}
以上代码就实现了继承, 其中 Student
结构体中嵌套了Person
结构体,且Person
必须作为匿名字段。
实例操作如下:
p1 := Person{name: "张三", age: 30}
fmt.Println("父类对象:", p1)
s1 := Student{Person{"李四", 17}, "清华大学"}
fmt.Println("子类对象 s1:", s1)
输出:
父类对象 p1: {张三 30}
子类对象 s1: {{李四 17} 清华大学}
刚刚在 (二)小节中,想通过student1.bookName
来直接访问书名是不允许,但是在本节学习了继承关系后,我们可以实现此操作了。
s3.Person.name = "王五"
s3.Person.age = 19
s3.school = "清华大学"
fmt.Println("子类对象 s3:", s3)
s3.name = "Ruby"
s3.age = 20
fmt.Println("子类对象 s3:", s3)
输出:
子类对象 s3: {{王五 19} 清华大学}
子类对象 s3: {{Ruby 20} 清华大学}
一般地,在实现了继承后,开发习惯通常都是直接子类对象.字段名来获取属性值。
但是如果有多重继承的情况,那就得指定访问哪个父类的属性。否则父类之间字段名重复的话,会引起访问歧义,编译会报错。
我们新增一个Teenager
结构体,其中age
字段和Person
的age
字段完成相同,然后Student
也继承它:
type Teenager struct {
age int
}
type Student struct {
Person
Teenager
school string
}
Teenager
和Person
结构体有个相同的字段 age
,访问时需要显示指定是访问哪个父类下的age
。否则会编译报错。
我们还是使用之前的直接访问属性的方式:
s3.name = "Ruby"
s3.age = 16
fmt.Println("子类对象 s3:", s3)
我们试着输出下报错信息:
# command-line-arguments
.\demo09_struct_extend.go:51:4: ambiguous selector s3.age
ambiguous selector s3.age
表明s3.age
有歧义,因为我们Person
和Teenager
有完全相同的字段。
2.结构体嵌套is a
和has a
区别
总结一下:
Golang结构体嵌套,会衍生出两种关系:
1.模拟继承性 - > is a
,如下:
type A struct{
field
}
type B struct{
A
}
2.模拟聚合性 - > has a
,如下:
type C struct{
field
}
type D struct{
c C
}
语法上的区别就是:嵌套的结构体是否匿名
结构体的记录暂时记录到这里,如果后续有新的知识,会持续更新。
Golang学习