Go 面向对象编程之继承

    技术2024-11-02  26

    面向对象编程之继承

    看一个问题,引出继承的必要性 一个小问题,看个学生考试系统的程序 ,提出代码复用的问题 package main import ( "fmt" ) //编写一个学生考试系统 //小学生 type Pupil struct { Name string Age int Score int } //显示他的成绩 func (p *Pupil) ShowInfo() { fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", p.Name, p.Age, p.Score) } func (p *Pupil) SetScore(score int) { //业务判断 p.Score = score } func (p *Pupil) testing() { fmt.Println("小学生正在考试中.....") } //大学生, 研究生。。 //大学生 type Graduate struct { Name string Age int Score int } //显示他的成绩 func (p *Graduate) ShowInfo() { fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", p.Name, p.Age, p.Score) } func (p *Graduate) SetScore(score int) { //业务判断 p.Score = score } func (p *Graduate) testing() { fmt.Println("大学生正在考试中.....") } //代码冗余.. 高中生.... func main() { //测试 var pupil = &Pupil{ Name :"tom", Age : 10, } pupil.testing() pupil.SetScore(90) pupil.ShowInfo() //测试 var graduate = &Graduate{ Name :"mary", Age : 20, } graduate.testing() graduate.SetScore(90) graduate.ShowInfo() } 对上面代码的小结 Pupil 和 Graduate 两个结构体的字段和方法几乎,但是我们却写了相同的代码, 代码复用性不强出现代码冗余,而且代码不利于维护,同时也不利于功能的扩展。解决方法-通过继承方式来解决

    继承基本介绍和示意图

    继承可以解决代码复用,让我们的编程更加靠近人类思维。当多个结构体存在相同的属性(字段)和方法时 可以从这些结构体中抽象出结构体(比如刚才的Student)在该结构体中定义这些相同的属性和方法。其它的结构体不需要重新定义这些属性(字段)和方法,只需嵌套一个 Student 匿名结构体即可。示意图如下:

    也就是说:在 Golang 中,如果一个 struct 嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。

    嵌套匿名结构体的基本语法

    type Goods struct { Name string Price int } type Book struct { Goods -- 这里就是嵌套匿名结构体 Goods Writer string }

    演示案例

    package main import ( "fmt" ) //编写一个学生考试系统 type Student struct { Name string Age int Score int } //将Pupil 和 Graduate 共有的方法也绑定到 *Student func (stu *Student) ShowInfo() { fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", stu.Name, stu.Age, stu.Score) } func (stu *Student) SetScore(score int) { //业务判断 stu.Score = score } //给 *Student 增加一个方法,那么 Pupil 和 Graduate都可以使用该方法 func (stu *Student) GetSum(n1 int, n2 int) int { return n1 + n2 } //小学生 type Pupil struct { Student //嵌入了Student匿名结构体 } //显示他的成绩 //这时Pupil结构体特有的方法,保留 func (p *Pupil) testing() { fmt.Println("小学生正在考试中.....") } //大学生, 研究生。。 //大学生 type Graduate struct { Student //嵌入了Student匿名结构体 } //显示他的成绩 //这时Graduate结构体特有的方法,保留 func (p *Graduate) testing() { fmt.Println("大学生正在考试中.....") } //代码冗余.. 高中生.... func main() { //当我们对结构体嵌入了匿名结构体使用方法会发生变化 pupil := &Pupil{} pupil.Student.Name = "tom" pupil.Student.Age = 8 pupil.testing() pupil.Student.SetScore(70) pupil.Student.ShowInfo() fmt.Println("res=", pupil.Student.GetSum(1, 2)) graduate := &Graduate{} graduate.Student.Name = "mary" graduate.Student.Age = 28 graduate.testing() graduate.Student.SetScore(90) graduate.Student.ShowInfo() fmt.Println("res=", graduate.Student.GetSum(10, 20)) } 输出结果:

    继承给编程带来的便利 代码的复用性提高了代码的扩展性和维护性提高
    Processed: 0.010, SQL: 9