Golang的继承模拟实例

 更新时间:2021年06月29日 12:02:55   作者:恋喵大鲤鱼  
这篇文章主要介绍了Go语言使用组合的方式实现多继承的方法,实例分析了多继承的原理与使用组合方式来实现多继承的技巧,需要的朋友可以参考下,希望可以帮助到你

1.前言

面向对象编程的三大特性:封装、继承、多态。可见继承是面向对象程序设计中一个重要的概念。Go 作为面向对象的编程语言,自然也支持继承。

比较特殊的是 Go 实现继承的方式与其他传统 OOP 语言所有不同,不像 C++ 有专门的继承语法,或者像 Java 中有专门的关键字 extends。

C++ 的继承:

// 基类
class Animal {
public:
    void eat(); 
	void sleep();
};


// 子类
class Dog : public Animal {
public:
    void bark();
};

Java 的继承:

// 基类
public class Animal {
	public void eat(){};
	public void sleep(){};
}
// 子类
public class Dog extends Animal {
	public void bark(){};
}

2.嵌入式继承机制

Go 使用匿名嵌套实现继承。

我们用很容易理解的动物-猫来举例子。

type Animal struct {
	Name string
}
func (a *Animal) Eat() {
	fmt.Printf("%v is eating", a.Name)
	fmt.Println()
}
type Cat struct {
	Animal
}
cat := &Cat{
	Animal: Animal{
		Name: "cat",
	},
}
cat.Eat() // cat is eating

首先,我们实现了一个 Animal 的结构体,代表动物类。并声明了 Name 字段,用于描述动物的名字。

然后,实现了一个以 Animal 为 receiver 的 Eat 方法,来描述动物进食的行为。

最后,声明了一个 Cat 结构体,组合了 Cat 字段。再实例化一个猫,调用Eat方法,可以看到会正常的输出。

可以看到,Cat 结构体本身没有 Name 字段,也没有去实现 Eat() 方法。唯一有的就是匿名嵌套的方式继承了 Animal 父类,至此,我们证明了 Go 通过匿名嵌套的方式实现了继承。

上面是嵌入类型实例,同样地也可以嵌入类型指针。

type Cat struct {
	*Animal
}
cat := &Cat{
	Animal: &Animal{
		Name: "cat",
	},
}

3.嵌入式继承机制的的局限

相比于 C++ 和 Java, Go 的继承机制的作用是非常有限的,因为没有抽象方法,有很多的设计方案可以在 C++ 和 Java 中轻松实现,但是 Go 的继承却不能完成同样的工作。

package main
import "fmt"
// Animal 动物基类
type Animal struct {
	name string
}
func (a *Animal) Play() {
	fmt.Println(a.Speak())
}
func (a *Animal) Speak() string {
	return fmt.Sprintf("my name is %v", a.name)
}
func (a *Animal) Name() string {
	return a.name
}
// Dog 子类狗
type Dog struct {
	Animal
	Gender string
}
func (d *Dog) Speak() string {
	return fmt.Sprintf("%v and my gender is %v", d.Animal.Speak(), d.Gender)
}
func main() {
	d := Dog{
		Animal: Animal{name: "Hachiko"},
		Gender:  "male",
	}
	fmt.Println(d.Name())
	fmt.Println(d.Speak())
	d.Play() // Play() 中调用的是基类 Animal.Speak() 方法,而不是 Dog.Speak()
}

运行输出:

Hachiko
my name is Hachiko and my gender is male
my name is Hachiko

上面的例子中,Dog 类型重写了 Speak() 方法。然而如果父类型 Animal 有另外一个方法 Play() 调用 Speak() 方法,但是 Dog 没有重写 Play() 的时候,Dog 类型的 Speak() 方法则不会被调用,因为 Speak() 方法不是抽象方法,此时继承无法实现多态。

4.使用接口封装方法

为了解决上面的问题,我们应该使用接口封装方法,通过实现接口方法来实现多态。

package main
import (
    "fmt"
)
type Animal interface {
    Name() string
    Speak() string
    Play()
}
type Dog struct {
    name string
    gender string
}
func (d *Dog) Play() {
    fmt.Println(d.Speak())
}
func (d *Dog) Speak() string {
    return fmt.Sprintf("my name is %v and my gender is %v", d.name, d.gender)
}
func (d *Dog) Name() string {
    return d.name
}
func Play(a Animal) {
    a.Play()
}
func main() {
    d :=&Dog{"Hachiko", "male"}
    fmt.Println(d.Name())
    fmt.Println(d.Speak())
    Play(d)
}

运行输出:

Hachiko
my name is Hachiko and my gender is male
my name is Hachiko and my gender is male

注意:Go 中某个类型需要实现接口中的所有方法才算作实现了接口。

5.小结

如果一个 struct 嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的属性和方法,从而实现继承。

如果一个 struct 嵌套了另一个有名的结构体,那么这个模式叫做组合。

如果一个 struct 嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的属性和方法,从而实现多重继承。

本篇文章就到这里了,希望能帮助到你,也希望您能多多关注脚本之家的更多内容!

相关文章

  • Go日志框架zap增强及源码解读

    Go日志框架zap增强及源码解读

    这篇文章主要为大家介绍了Go日志框架zap增强及源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 一文完全掌握 Go math/rand(源码解析)

    一文完全掌握 Go math/rand(源码解析)

    这篇文章主要介绍了一文完全掌握 Go math/rand(源码解析),本文可以帮助大家快速使用Go Rand.,感兴趣的朋友跟随小编一起看看吧
    2021-04-04
  • Golang工具库viper的使用教程

    Golang工具库viper的使用教程

    viper 是 go 项目中用来读取配置文件的库,支持读取 yaml、toml、json、hcl、env 等格式的配置文件,下面就来和大家聊聊它的具体使用吧
    2023-07-07
  • 一文带你了解如何正确理解和使用Golang中nil

    一文带你了解如何正确理解和使用Golang中nil

    在 Golang 中,nil 是一个预定义的标识符,在不同的上下文环境中有不同的含义,但通常表示“无”、“空”或“零值”,本文主要来带大家了解下nil的正确使用,需要的可以参考下
    2023-12-12
  • Golang字符串的拼接方法汇总

    Golang字符串的拼接方法汇总

    字符串拼接在日常开发中是很常见的需求,今天我们来探讨下如何用golang来实现字符串的拼接
    2018-10-10
  • golang 调用c语言动态库方式实现

    golang 调用c语言动态库方式实现

    本文主要介绍了golang 调用c语言动态库方式实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Golang中正则表达式语法及相关示例

    Golang中正则表达式语法及相关示例

    正则表达式是一种用于匹配和操作文本的强大工具,它使用特殊的字符和语法来定义模式,下面这篇文章主要给大家介绍了关于Golang中正则表达式语法及相关示例的相关资料,需要的朋友可以参考下
    2024-05-05
  • GoFrame通用类型变量gvar与interface基本使用对比

    GoFrame通用类型变量gvar与interface基本使用对比

    这篇文章主要为大家介绍了GoFrame通用类型变量gvar与interface基本使用对比,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 深入理解Go语言中的结构体

    深入理解Go语言中的结构体

    本文主要介绍了深入理解Go语言中的结构体,包括定义结构体、声明结构体变量、使用结构体、结构体关联函数、new、组合等,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-11-11
  • golang http请求未释放造成的错误问题

    golang http请求未释放造成的错误问题

    这篇文章主要介绍了golang http请求未释放造成的错误问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论