总结两点:

  • 在Go中,定义一个interface类型,该类型说明了它有哪些方法。使用时,在函数中,将该interface类型作为函数的形参,任意一个实现了interface类型的实参都能作为该interface的实例对象。Go中没有implements关键字,与Java的实现多态相比,Go的组合更加灵活。
  • Go语言中没有继承,只有组合,可通过组合达到“继承”方法的目的。

先看一个例子:

/**
* Animal 三个接口:fly(), swim() 和 run(),如果实现Animal,需要同时实现三个接口。
*/
public interface Animal {
public void fly();
public void swim();
public void run();
} class Dog implements Animal {
@Override
public void fly() {
System.out.println("Dog can not fly");
} @Override
public void swim() {
System.out.println("Dog can not swim");
} @Override
public void run() {
System.out.println("Dog can run");
}
} class Fish implements Animal {
@Override
public void fly() {
System.out.println("Fish can not fly");
} @Override
public void swim() {
System.out.println("Fish can swim");
} @Override
public void run() {
System.out.println("Fish can not run");
}
}

再来看Go的实现:

type Animal1 interface {
fly()
swim()
run()
} type Dog1 struct {
} func (d Dog1) run() {
fmt.Println("dog can run")
} type Fish struct {
} func (f Fish) swim() {
fmt.Println("fish can swim")
}

可以看到,Go中实现需要的功能更灵活。这是多个实现类之间的比较,实现更加灵活。再看类似于“父子”之间的继承。

import (
"fmt"
"reflect"
) type Base struct {
// nothing
} func (b *Base) ShowA() {
fmt.Println(reflect.TypeOf(b))
fmt.Println("showA")
b.ShowB()
}
func (b *Base) ShowB() {
fmt.Println(reflect.TypeOf(b))
fmt.Println("showB")
} func (b *Base) ShowC() {
fmt.Println(reflect.TypeOf(b))
fmt.Println("showC")
}
//Derived 通过组合Base结构体,实现了伪继承,即拥有了ShowA和ShowB方法
type Derived struct {
Base
}
//Derived 自己实现了ShowB方法,但不会自动做类型转换
func (d *Derived) ShowB() {
fmt.Println(reflect.TypeOf(d))
fmt.Println("Derived showB")
} type NewBase Base func main2() {
d := Derived{Base{}}
d.ShowA() //Derived通过组合,有了ShowA()方法
/**
*main.Base
showA
*main.Base
showB
上述代码执行结果不会输出“Derived showB”,因为Go中没有继承的概念,只有组合.
上面的Derived包含了Base,自动的含有了Base的方法,因为其不是继承,所以不会根据具体传入的对象而执行对应的方法。
*/
d.ShowB()
/**
*main.Derived
Derived showB
*/ d.Base.ShowB()
/**
*main.Base
showB
d 通过组合获取了Base的方法 ShowB. 但如果d要调取Base的ShowB()方法(与d的ShowB()方法重复),需要显示调用Base.
*/
d.ShowC()
/**
*main.Base
showC
d 通过组合获取了Base的方法 ShowC.
*/
b := Base{}
b.ShowC()
//b1 := NewBase{}
//b1.ShowC() //没有ShowC()方法
/**
上面的代码中b1不能执行ShowC()函数,因为Golang不支持隐式类型转换.
虽然newBase就是Base,但语法上它们是两种类型,因此newBase不能执行ShowC()方法。
*/
}

理解Go的多态实现的更多相关文章

  1. 深入理解OOP(三):多态和继承(动态绑定和运行时多态)

    在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...

  2. 深入理解OOP(二):多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...

  3. Java基础之理解封装,继承,多态三大特性

    目录 封装 继承 多态 封装 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 代码理解 publ ...

  4. 深入理解.net - 2.多态 Polymorphsim

    通过上篇文章 继承的本质 深入介绍了继承过程中对象的的创建过程,相信对继承已经有了一个深入的理解,本文则详细剖析一下面向对象设计的另一要素多态(Polymorphsim). 什么是多态 官方MSDN上 ...

  5. 看懂下面C++代码才说你理解了C++多态虚函数!

    #include <iostream> using namespace std ; class Father { private :  virtual void Say()  //只有添加 ...

  6. 理解java的 多态

    http://www.cnblogs.com/chenssy/p/3372798.html

  7. 深入理解OOP(四): 多态和继承(抽象类)

    在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. 深入理解OOP(一):多态和继承(初期绑定 ...

  8. 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  9. python中对多态的理解

    目录 python中对多态的理解 一.多态 二.多态性 三.鸭子类型 python中对多态的理解 一.多态 多态是指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等.(一个抽象类有多个子类,因而多 ...

随机推荐

  1. 在IDEA中使用JDBC获取数据库连接时的报错及解决办法

    在IDEA中使用JDBC获取数据库连接时,有时会报错Sat Dec 19 19:32:18 CST 2020 WARN: Establishing SSL connection without ser ...

  2. webshell学习

    参考文章: https://www.bilibili.com/video/BV1T4411t7BW?p=14 https://blog.csdn.net/mmmsss987/article/detai ...

  3. 微服务痛点-基于Dubbo + Seata的分布式事务(AT)模式

    前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...

  4. python函数收集不确定数量的值

    python写函数的时候,有时候会不确定到底传入多少值. 首先是,*args,单星号参数收集参数: 1 #!usr/bin/python 2 #-*-coding:utf-8-*- 3 4 #定义一个 ...

  5. 华为---MGRE实验--内网为RIP

    数据链路层封装技术总结: 实验要求与拓扑: 1. 配置IP地址 公网IP地址:12.1.1.0/24.23.1.1.0/24.24.1.1.0/24 tunnel地址:1.1.1.1/24.1.1.1 ...

  6. Linux嵌入式学习-远程过程调用-Binder系统

    Binder系统的C程序使用示例IPC : Inter-Process Communication, 进程间通信RPC : Remote Procedure Call, 远程过程调用 这里我们直接只用 ...

  7. OpenResty 简介

    OpenResty 简介 OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台.我们知道开发 Nginx 的模块需要用 C 语言,同时还要熟悉它的源码,成本和门槛比较高.国人 ...

  8. 跟我一起学python(1):占位符

    模板 格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格式.Python用一个tuple将多个值传递给模板,每个值对应一个格式符 ...

  9. TurtleBot3 Waffle (tx2版华夫)(3)opencr系统安装

    3. 1. 安装 Arduino IDE Opencr的安装环境的安装包,双击打开即可.进入安装的过程. 在这里你可以选择自己的安装位置. 安装已经完成,点击CLOSE 即可. 3.2. opencr ...

  10. Java ClassLoader浅析

    双亲委派 提起 java 类加载器,自然绕不开其双亲委派模型 什么是双亲委派 提起双亲委派,首先想到便是那张经典的向上委派图 一般场景下,当某个类将要被加载时,由系统上下文默认的类加载器Thread. ...