golang实现面向对象的封装、继承、多态

摘要:
封装、继承、多态和抽象是面向对象的四个基本特征。

1. 基本介绍

面向对象程序设计(Object Oriented Programming,OOP)是一种计算机编程框架,尽可能的模拟人类的思维方式,使得软件的开发方法与过程尽可能接近人类认识世界、解决现实问题的方法和过程。

封装、继承、多态和抽象是面向对象的4个基本特征。

2. golang的面向对象类型

  1. golang实现面向对象的两个关键类型是struct 和interface,struct类似于C++的普通类类型,interface则对应抽象类类型。
  2. 同时与其他语言采用public、private、protected指示成员和方法的可见性不同,golang采用首字母大小写来标识成员/方法的可见性,小写字母开头表示私有成员,大写字母开头表示对外可见。

1、封装

  1. 基本介绍:封装就是把抽象出的字段和字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作(方法)才能对字段进行操作
  2. 优点:隐藏实现细节;可以对数据进行验证。
  3. 实现如下面代码所示,需要注意的是,在golang内,除了slice、map、channel和显示的指针类型属于引用类型外,其它类型都属于值类型。
    1. 引用类型作为函数入参传递时,函数对参数的修改会影响到原始调用对象的值;
    2. 值类型作为函数入参传递时,函数体内会生成调用对象的拷贝,所以修改不会影响原始调用对象。所以在下面GetName中,接收器使用 this *Person 指针对象定义。当传递的是小对象,且不需要更改调用对象时,使用值类型做为接收器;大对象或者需要更改调用对象时使用指针类型作为接收器。
type Person struct {
	name string
	age int
}

func NewPerson() Person {
	return Person{}
}

func (this *Person) SetName(name string) {
	this.name = name
}
func (this *Person) GetName() string {
	return this.name
}

func (this *Person) SetAge(age int) {
	this.age = age
}
func (this *Person) GetAge() string {
	return this.age
}

func main() {
	p := NewPerson()
	p.SetName("xiaofei")
	fmt.Println(p.GetName())
}

2、继承

  1. 基本介绍:当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出一个基结构体A,在A中定义这些相同的属性和方法。其他的结构体不需要重新定义这些属性和方法,只需嵌套一个匿名结构体A即可。
  2. 优点:可以解决代码复用,让编程更加靠近 人类思维。
  3. 实现:在golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现继承特性。
  4. 同时,一个struct还可以嵌套多个匿名结构体,那么该struct可以直接访问嵌套的匿名结构体的字段和方法,从而实现多重继承。
type Student struct {
	Person
	StuId int
}

func (this *Student) SetId(id int) {
	this.StuId = id
}
func (this *Student) GetId() int {
	return this.StuId
}
func main() {
	stu := oop.Student{}

	stu.SetName("xiaofei")  // 可以直接访问Person的Set、Get方法
	stu.SetAge(22)
	stu.SetId(123)

	fmt.Printf("I am a student,My name is %s, my age is %d, my id is %d", stu.GetName(), stu.GetAge(), stu.GetId)
}

3、抽象

将共同的属性和方法抽象出来形成一个不可以被实例化的类型,由于抽象和多态是相辅相成的,或者说抽象的目的就是为了实现多态。

4、多态

  1. 基本介绍:基类指针可以指向任何派生类的对象,并在运行时绑定最终调用的方法的过程被称为多态。多态是运行时特性,而继承则是编译时特性,也就是说继承关系在编译时就已经确定了,而多态则可以实现运行时的动态绑定。
  2. 实现:
// 小狗和小鸟都是动物,都会移动和叫,它们共同的方法就可以提炼出来定义为一个抽象的接口。
type Animal interface {
	Move()
	Shout()
}

type Dog struct {
}

func (dog Dog) Move() {
	fmt.Println("I am dog, I moved by 4 legs.")
}
func (dog Dog) Shout() {
	fmt.Println("WANG WANG WANG")
}

type Bird struct {
}

func (bird Bird) Move() {
	fmt.Println("I am bird, I fly with 2 wings")
}
func (bird Bird) Shout() {
	fmt.Println("ji ji ji ")
}

type ShowAnimal struct {
}

func (s ShowAnimal) Show(animal Animal) {
	animal.Move()
	animal.Shout()
}

func main() {
	show := ShowAnimal{}
	dog := Dog{}
	bird := Bird{}

	show.Show(dog)
	show.Show(bird)
}

参考资料:

  1. https://blog.csdn.net/weixin_44736475/article/details/114222071
  2. https://blog.csdn.net/weixin_44736475/article/details/114177630
  3. https://blog.csdn.net/weixin_44736475/article/details/114181543
  4. https://blog.csdn.net/m0_37554486/article/details/77404739

免责声明:文章转载自《golang实现面向对象的封装、继承、多态》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇企业微信开发之向员工付款(C#)replace into 批量更新下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【Java面向对象 05】

一、构造方法 1、方法名与类名称相同,2、没有返回值,不需要void关键字2、调用类里面的属性必须先进行对象的引用,即:new 类名(),引用:引用名.属性以下举例:Test01类对Students类进行初始化调用,Test02类对Students类进行属性的修改,即修改成员变量 public class Students { //学号 i...

由endl对printf和cout的思考

【前言】二者的区别就不介绍了。二者使用方法: printf("%s",a); cout<<a<<endl; endl的作用是什么? 一、endl作用 众所周知,endl有一个换行的作用,第二个作用就是清空缓冲区buffer。 为什么要清空缓冲区呢? 首先思考缓冲区存在的作用,缓冲区的作用一是为了避免频繁的I/O操作对磁盘的损耗,...

macbook golang的debug模式不好使

因为新版mac运用了m1芯片,所以golang在debug的时候会有报错,具体如下: can not run under rosetta check that the installed build of go is right for your cpu architecture 就是cpu架构的问题,所以我们安装arm架构的golang版本即可。具体版本...

Java——多态

一、什么是多态 事物的多种展现形式。 二、多态的好处 提高程序中代码的复用性、扩展性 三、多态的前提 有继承关系、实现关系 子类重写父类/父接口中的方法 四、多态的书写格式 父类/父接口 父引用 = new 子类(); // 父引用指向子类对象 JavaStudent javaStu = new JavaStudent(); // 使用事物...

C#基础知识

C#基础 1、面向对象、面向接口、面向方向编程的区别: 面向对象:强调对具有相同行为和属性事物的封装,更注重封装的完整性和功能的完整性 面向接口:定义要实现某类功能要实现的统一规范,而具体实现过程由实现该接口的类型决定 面向方面:主要提供与业务逻辑无关的操作。比如系统中多个地方要使用到的文件上传功能,可以使用面向方向的思想在所有上传文件之前对文件的大小、格...

Golang的time.NewTicker周期性定时器使用案例

 Ticker是一个周期触发定时的计时器,它会按照一个时间间隔往channel发送系统当前时间,而channel的接收者可以以固定的时间间隔从channel中读取事件。 一.通过NewTicker函数定义定时器 package main import ( "fmt" "time" ) func main() { //创建...