go语言笔记(七)面向对象_继承

go语言笔记(七)面向对象_继承

为什么需要继承

案例:

创建小学生结构体和大学生结构体,并实现一些基本方法,如查看信息、考试、填写成绩等。

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 Undergraduate struct {
	Name  string
	Age   int
	Score int
}

//显示他的成绩
func (p *Undergraduate) ShowInfo() {
	fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", p.Name, p.Age, p.Score)
}
func (p *Undergraduate) SetScore(score int) {
	//业务判断
	p.Score = score
}
func (p *Undergraduate) testing() {
	fmt.Println("大学生正在考试中.....")
}

//代码冗余.. 高中生....
func main() {
	//测试
	var pupil = &Pupil{
		Name: "Tom",
		Age:  10,
	}
	pupil.testing()
	pupil.SetScore(90)
	pupil.ShowInfo()
	//测试
	var graduate = &Undergraduate{
		Name: "Mary",
		Age:  20,
	}
	graduate.testing()
	graduate.SetScore(90)
	graduate.ShowInfo()
}

以上案例中,创建了两种结构体类型:小学生类型和大学生类型。

我们发现两个结构体的基本属性一致,且共享了一些基础操作比如输入成绩以及ShowInfo方法等,但是各自的testing方法实现的内容却不相同。

以此类推,假如还要创建高中生变量、初中生变量等,我们需要重复定义他们的基本属性和操作,造成代码冗余。同时不利于功能扩展。

继承可以实现代码复用,让我们的编程更加靠近人类思维。当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体(比如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
}

//显示他的成绩
func (s *Student) ShowInfo() {
	fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", s.Name, s.Age, s.Score)
}
func (s *Student) SetScore(score int) {
	//业务判断
	s.Score = score
}

type Pupil struct {
	Student
}

func (p *Pupil) testing() {
	fmt.Println("小学生在考试...")
}

type Undergraduate struct {
	Student
}

func (u *Undergraduate) testing() {
	fmt.Println("大学生在考试...")
}

func main() {
	//当我们对结构体嵌入了匿名结构体使用方法会发生变化
	pupil := &Pupil{}
	pupil.Student.Name = "tom~"
	pupil.Student.Age = 8
	pupil.testing()
	pupil.Student.SetScore(70)
	pupil.Student.ShowInfo()
	graduate := &Undergraduate{}
	graduate.Student.Name = "mary~"
	graduate.Student.Age = 28
	graduate.testing()
	graduate.Student.SetScore(90)
	graduate.Student.ShowInfo()
}

通过以上改进,代码的复用性提高。且更加容易扩展和维护

继承的深入探讨

1.结构体可以使用嵌套匿名结构体的所有字段和方法,无论首字母大小写都可以使用。

2.匿名结构体字段访问和方法调用可以简化,如:

A.B.Name//B为匿名结构体

可以直接简化为

A.Name

其实现的原理在于编译器在查找Name字段时先在A中查找,如果A中没有就会在A嵌套的匿名结构体B中查找。

3.当结构体和匿名结构体含有相同名称的字段或者方法且采取简化调用时,采取就近原则,首先访问结构体本身的字段或方法。

4.当结构体中嵌套了两个匿名结构体,那么在调用相同名称字段或方法时就不能使用简化方法,否则会报错。(多重继承)*为了保证代码的简洁性,尽量不要使用多重继承

5.如果嵌套了有名结构体,这种模式称为组合。在访问组合的字段或方法时不能简写,得写上嵌套的结构体的变量名。

称的字段或者方法且采取简化调用时,采取就近原则,首先访问结构体本身的字段或方法。

4.当结构体中嵌套了两个匿名结构体,那么在调用相同名称字段或方法时就不能使用简化方法,否则会报错。(多重继承)*为了保证代码的简洁性,尽量不要使用多重继承

5.如果嵌套了有名结构体,这种模式称为组合。在访问组合的字段或方法时不能简写,得写上嵌套的结构体的变量名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洞爷湖dyh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值