【一Go到底】第四十四天---面向对象编程之继承

99 阅读3分钟

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

一、为什么需要继承

1.1 案例

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) Exam() {
	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) Exam() {
	fmt.Println("大学生正在考试........")
}

func main() {
	//
	var p = &Pupil{
		Name: "力王",
		Age:  10,
	}
	// 小学生正在考试........
	p.Exam()
	p.SetScore(95)

	// 学生名字:力王, 年龄:10, 成绩:95
	p.ShowInfo()

	// 大学生
	var g = &Graduate{
		Name: "大力王",
		Age:  20,
	}
	// 大学生正在考试........
	g.Exam()
	g.SetScore(150)

	// 学生名字:大力王, 年龄:10, 成绩:95
	g.ShowInfo()

}

1.2 案例解析

  1. Pupil 和 Graduate 两个结构体字段和方法几乎一样,但是在声明使用时却写了同样的代码
  2. 出现代码冗余,不利于代码维护,不利于功能拓展
  3. 解决方法: 继承方法实现

1.3 继承基本介绍

  1. 继承可以解决代码复用,让我们的编程更加靠近人类思维。
  2. 当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体(比 如刚才的Student),在该结构体中定义这些相同的属性和方法。
  3. 其它的结构体不需要重新定义这些属性和方法,只需嵌套一个Student匿名结构体即 可。
  4. 也就是说:在Golang中,如果-一个struct嵌套了另一个匿名结构体,那么这个结构 体可以直接访问匿名结构体的字段和方法,从而实现了继承特性

1.4 基本语法

type Goods struct{
    Name string
    Price int
}

type Book struct{
    Goods //嵌套匿名结构体Goods
    Writer string
}

1.5 快速入门案例(改进1.1)

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
}

func (stu *Student) GetScore() int {
	return stu.Score
}

func (stu *Student) getSum(x int, y int) int {
	return x + y
}

//小学生
type Pupil struct {
	Student // 嵌入匿名结构体
}

// 显示成绩方法

// 这是特有方法,保留
func (p *Pupil) Exam() {
	fmt.Println("小学生正在考试........")
}

// 大学生
type Graduate struct {
	Student // 嵌入匿名结构体
}

// 显示成绩方法
// 这是特有方法,保留
func (p *Graduate) Exam() {
	fmt.Println("大学生正在考试........")
}

func main() {
	//
	pupil := &Pupil{}
	pupil.Student.Name = "小力王"
	pupil.Student.Age = 8
	// 小学生正在考试........
	pupil.Exam()

	// 设置小学生分数
	// 小学生正在考试........
	// 学生名字:小力王, 年龄:8, 成绩:88
	pupil.Student.SetScore(88)
	pupil.Student.ShowInfo()

	graduate := &Graduate{}

	graduate.Student.Name = "大力王"
	graduate.Student.Age = 22
	// 大学生正在考试........
	// 学生名字:大力王, 年龄:22, 成绩:149
	graduate.Exam()
	graduate.Student.SetScore(149)
	graduate.Student.ShowInfo()

	// 测试Student里面的getSum
	// Student GetSum =  30
	fmt.Println("Student GetSum = ", pupil.Student.getSum(10, 20))

}

1.6 继承的好处

  1. 提高代码复用性
  2. 提高代码的扩展性和维护性