Go 继承的深入讨论以及多继承

    技术2025-01-29  8

    继承的深入讨论

    结构体可以使用嵌套匿名结构体所有的字段和方法 首字母大写或者小写的字段、方法,都可以使用。 type A struct { Name string age int } func (a *A) SayOk() { fmt.Println("A SayOk", a.Name) } func (a *A) hello() { fmt.Println("A hello", a.Name) } type B struct { A } func main() { var b B b.A.Name = "tom" b.A.age = 19 b.A.SayOk() b.A.hello() } 输出:


    匿名结构体字段访问可以简化 type A struct { Name string age int } func (a *A) SayOk() { fmt.Println("A SayOk", a.Name) } func (a *A) hello() { fmt.Println("A hello", a.Name) } type B struct { A } func main() { b.Name = "smith" b.age = 20 b.SayOk() b.hello() } 输出:


    对上面的代码小结 当我们直接通过 b 访问字段或方法时,其执行流程如下比如 b.Name编译器会先看 b 对应的类型有没有 Name, 如果有,则直接调用 B 类型的 Name 字段如果没有就去看 B 中嵌入的匿名结构体 A 有没有声明 Name 字段,如果有就调用,如果没有继续查找..如果都找不到就报错.当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问 如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分 type A struct { Name string age int } func (a *A) SayOk() { fmt.Println("A SayOk", a.Name) } func (a *A) hello() { fmt.Println("A hello", a.Name) } type B struct { A Name string } func (b *B) SayOk() { fmt.Println("B SayOk", b.Name) } func main() { var b B b.Name = "jack" // ok b.A.Name = "scott" b.age = 100 //ok b.SayOk() // B SayOk jack b.A.SayOk() // A SayOk scott b.hello() // A hello ? "jack" 还是 "scott" } 输出结果:


    结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。 type A struct { Name string age int } type B struct { Name string Score float64 } type C struct { A B //Name string } func main() { var c C -- 如果c 没有Name字段,而A 和 B有Name, 这时就必须通过指定匿名结构体名字来区分 -- 所以 c.Name 就会包编译错误, 这个规则对方法也是一样的! c.A = "tom" -- error c.A.Name = "tom" -- 正确 fmt.Println("c") }
    如果一个 struct 嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字 type A struct { Name string age int } type B struct { Name string Score float64 } type D struct { a A -- 有名结构体 } func main() { -- 如果D 中是一个有名结构体,则访问有名结构体的字段时,就必须带上有名结构体的名字 -- 比如 d.a.Name var d D d.a.Name = "jack" }
    嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值 type Goods struct { Name string Price float64 } type Brand struct { Name string Address string } type TV struct { Goods Brand } func main() { //嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值 tv := TV{ Goods{"电视机001", 5000.99}, Brand{"海尔", "山东"}, } tv2 := TV{ Goods{ Price : 5000.99, Name : "电视机002", }, Brand{ Name : "夏普", Address :"北京", }, } } 或者嵌套指针类型: type Goods struct { Name string Price float64 } type Brand struct { Name string Address string } type TV2 struct { *Goods *Brand } func main() { fmt.Println("tv", tv) fmt.Println("tv2", tv2) tv3 := TV2{ &Goods{"电视机003", 7000.99}, &Brand{"创维", "河南"}, } tv4 := TV2{ &Goods{ Name : "电视机004", Price : 9000.99, }, &Brand{ Name : "长虹", Address : "四川", }, } }
    结构体的匿名字段是基本数据类型,如何访问, 下面代码输出什么 type Monster struct { Name string Age int } type E struct { Monster int n int } func main() { //匿名字段时基本数据类型的使用 var e E e.Name = "Tom" e.Age = 300 e.int = 20 e.n = 40 fmt.Println("e=", e) } 输出结果: 说明 如果一个结构体有 int 类型的匿名字段,就不能第二个。如果需要有多个 int 的字段,则必须给 int 字段指定名字

     

    多重继承

    多重继承说明 如一个 struct 嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。案例演示


    多重继承细节说明 如嵌入的匿名结构体有相同的字段名或者方法名,则在访问时,需要通过匿名结构体类型名来区分。

    为了保证代码的简洁性,建议大家尽量不使用多重继承
    Processed: 0.008, SQL: 9