go-继承与重写,实现抽象类

2,376 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情

继承

go不像java那样有extends关键字可以显示继承,go的继承是通过匿名字段。

package main

import "fmt"

type Staff struct {
   name  string //名称
   phone string //手机
}

func (staff Staff) doWork() {
   fmt.Println("just do")
}

type Manager struct {
   Staff          //匿名字段
   staffs []Staff //员工
}

func main() {
   staff := Staff{
      name:  "wh",
      phone: "176",
   }
   fmt.Println(staff)

   manager := Manager{
      Staff{
         name:  "wf",
         phone: "168",
      },
      []Staff{
         staff,
         {
            name:  "hf",
            phone: "177",
         },
      },
   }
   fmt.Println(manager)

   staff.doWork()
   manager.doWork()
}

输出:

{wh 176}
{{wf 168} [{wh 176} {hf 177}]}
just do
just do

看子类的构建,给我的感觉是组合而非继承,但是从子类调用父类的方法又像是继承了。

之所以不像java那样平级去构建是因为当同名的时候就需要其他关键字去区分,就像java为了区分子父是用来super,使用嵌套的形式去实现更加直接,这点我觉得比java更易上手。

子父类同名成员

下面看看go是怎实现子类和父类存在同名成员的:

package main

import "fmt"

type Staff struct {
   name  string //名称
   phone string //手机
}

func (staff Staff) doWork() {
   fmt.Println("just do")
}

type Manager struct {
   Staff          //匿名字段
   staffs []Staff //员工
   name   string
}

func main() {
   staff := Staff{
      name:  "wh",
      phone: "176",
   }
   fmt.Println(staff)

   manager := Manager{
      Staff: Staff{
         name:  "wf",
         phone: "168",
      },
      staffs: []Staff{
         staff,
         {
            name:  "hf",
            phone: "177",
         },
      },
      name: "dd",
   }
   fmt.Println(manager)

   //子类自己的name成员
   fmt.Println(manager.name)
   //子类父类的name成员
   fmt.Println(manager.Staff.name)

   staff.doWork()
   manager.doWork()
}

输出:

{wh 176}
{{wf 168} [{wh 176} {hf 177}] dd}
dd
wf
just do
just do

重写父类方法

package main

import "fmt"

type Staff struct {
   name  string //名称
   phone string //手机
}

func (staff Staff) doWork() {
   fmt.Println("just do")
}

type Manager struct {
   Staff          //匿名字段
   staffs []Staff //员工
   name   string
}

func (manager Manager) doWork() {
   fmt.Println("manager")
}

func main() {
   staff := Staff{
      name:  "wh",
      phone: "176",
   }
   fmt.Println(staff)

   manager := Manager{
      Staff: Staff{
         name:  "wf",
         phone: "168",
      },
      staffs: []Staff{
         staff,
         {
            name:  "hf",
            phone: "177",
         },
      },
      name: "dd",
   }
   fmt.Println(manager)

   //子类自己的name成员
   fmt.Println(manager.name)
   //子类父类的name成员
   fmt.Println(manager.Staff.name)

   staff.doWork()
   manager.doWork()
}

输出:

{wh 176}
{{wf 168} [{wh 176} {hf 177}] dd}
dd
wf
just do
manager

实现抽象类

package main

import "fmt"

type Staff struct {
   name      string //名称
   phone     string //手机
   breathing func(where string) string
}

func (this Staff) eat() {
   fmt.Print("吃吃吃")
   fmt.Println(this.breathing(",也要呼吸"))
}

type Manager struct {
   Staff          //匿名字段
   staffs []Staff //员工
}

type Boss struct {
   Manager
   mangers []Manager
}

func main() {
   staff := Staff{breathing: func(where string) string {
      s := "普通员工"
      return s + where
   }}
   staff.eat()
   
   manager := Manager{Staff: Staff{breathing: func(where string) string {
      s := "管理者"
      return s + where
   }}}
   manager.eat()

   boss := Boss{Manager: Manager{Staff: Staff{breathing: func(where string) string {
      s := "boss"
      return s + where
   }}}}
   boss.eat()
}

输出:

吃吃吃普通员工,也要呼吸
吃吃吃管理者,也要呼吸
吃吃吃boss,也要呼吸

说实话,不确定go有没有这样叫法,但是本质上实现了多态,人家go本来一切皆对类型,不管name string还是breathing func(where string) string都是前name后type,具体的初始化/实现是在构造的时候去弄的。