【一Go到底】第四十五天---继承深入讨论

160 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第45天,点击查看活动详情

一、注意事项

  1. 结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用。
  2. 匿名结构体字段访问可以简化
  3. 当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分
  4. 结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。
  5. 如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字
  6. 嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。

二、案例演示

2.1 细节一

package main

import "fmt"

type A struct {
	Name string
	age  int
}

func (a *A) SayOk() {
	fmt.Println("A SayOK ", *a)
}

func (a *A) hello() {
	fmt.Println("A hello ", *a)
}

type B struct {
	A
}

func main() {

	var b B
	b.A.Name = "毕用欸"
	b.A.age = 30
	// A SayOK  {毕用欸 30}
	// A hello  {毕用欸 30}
	b.A.SayOk()
	b.A.hello()
}

2.2 细节二

流程说明

  1. 直接通过b访问字段或方法时,其流程如下 b.Name
  2. 编译器先查看b对应的类型是否存在Name,如果有则直接调用B类型的Name字段
  3. 如果没有,去看B中嵌入匿名结构体中是否存在Name字段,如果有就调用,如果没有,就查找匿名结构体中的匿名结构体,如果都没有找到,则会报错
package main

import "fmt"

type A struct {
	Name string
	age  int
}

func (a *A) SayOk() {
	fmt.Println("A SayOK ", *a)
}

func (a *A) hello() {
	fmt.Println("A hello ", *a)
}

type B struct {
	A
}

func main() {

	var b B
	b.A.Name = "毕用欸"
	b.A.age = 30
	// A SayOK  {毕用欸 30}
	// A hello  {毕用欸 30}
	b.A.SayOk()
	b.A.hello()
	fmt.Println()

	// 简化语法

	b.Name = "毕用欸"
	b.age = 30
	// A SayOK  {毕用欸 30}
	// A hello  {毕用欸 30}
	b.SayOk()
	b.hello()

}


2.3 细节三

package main

import "fmt"

type A struct {
	Name string
	age  int
}

func (a *A) SayOk() {
	fmt.Println("A SayOK ", *a)
}

func (a *A) hello() {
	fmt.Println("A hello ", *a)
}

//  案例三
type B struct {
	A
	Name string
}

func (b *B) SayOK() {
	fmt.Println("B SayOK", b.Name)
}

func main() {

	var b B
	b.Name = "bob"
	b.age = 100

	// B SayOK bob
	// A hello  { 100}
	b.SayOK()
	b.hello()

	// 若想给A的Name赋值,那么需要如下
	// A hello  {Aliy 100}
	b.A.Name = "Aliy"
	b.hello()

}


2.4 细节四

package main

type A struct {
	Name string
	age  int
}

type B struct {
	Name string
}

// 案例四
type C struct {
	A
	B
}

func main() {
	var c C
	// 如果 C 没有Name字段,A和B有Name,必须通过指定匿名结构体名来区分

	c.A.Name = "AAAAA"
	c.B.Name = "BBBBB"

}

2.5 细节五

package main

type A struct {
	Name string
	age  int
}

type B struct {
	a A
}

func main() {
	var b B
	// 嵌套有名结构体
	b.a.Name = "c-----AAAAAA"

}

2.6 细节六

package main

import "fmt"

type Goods struct {
	Name  string
	Price float64
}

type Brand struct {
	Name string
	Add  string
}

type TV struct {
	Goods
	Brand
}

type TVPtr struct {
	*Goods
	*Brand
}

func main() {

	tv := TV{Goods{"电视机", 1999}, Brand{"小米", "China"}}
	// {{电视机 1999} {小米 China}}
	fmt.Println(tv)

	tv2 := TV{
		Goods{
			Name:  "4K电视机",
			Price: 4999,
		},
		Brand{
			Name: "索尼",
			Add:  "日本",
		},
	}
	// TV2 ===>  {{4K电视机 4999} {索尼 日本}}
	fmt.Println("TV2 ===> ", tv2)
	fmt.Println()

	// 使用指针方法
	tv3 := TVPtr{
		&Goods{
			Name:  "4K电视机",
			Price: 4999,
		},
		&Brand{
			Name: "三星",
			Add:  "韩国",
		},
	}
	// TVPtr ====>  {4K电视机 4999} {三星 韩国}
	fmt.Println("TVPtr ====> ", *tv3.Goods, *tv3.Brand)
}