理解Go的多态实现
总结两点:
- 在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的多态实现的更多相关文章
- 深入理解OOP(三):多态和继承(动态绑定和运行时多态)
在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...
- 深入理解OOP(二):多态和继承(继承)
本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...
- Java基础之理解封装,继承,多态三大特性
目录 封装 继承 多态 封装 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 代码理解 publ ...
- 深入理解.net - 2.多态 Polymorphsim
通过上篇文章 继承的本质 深入介绍了继承过程中对象的的创建过程,相信对继承已经有了一个深入的理解,本文则详细剖析一下面向对象设计的另一要素多态(Polymorphsim). 什么是多态 官方MSDN上 ...
- 看懂下面C++代码才说你理解了C++多态虚函数!
#include <iostream> using namespace std ; class Father { private : virtual void Say() //只有添加 ...
- 理解java的 多态
http://www.cnblogs.com/chenssy/p/3372798.html
- 深入理解OOP(四): 多态和继承(抽象类)
在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. 深入理解OOP(一):多态和继承(初期绑定 ...
- 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)
在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...
- python中对多态的理解
目录 python中对多态的理解 一.多态 二.多态性 三.鸭子类型 python中对多态的理解 一.多态 多态是指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等.(一个抽象类有多个子类,因而多 ...
随机推荐
- C语言中++*x和*++x的区别
++跟*的优先级一样,如果两个同时出现,运算是从右往左(不是常规的从左往右),所以: ++*x即++(*x),先取x的值,然后让值自加1:(地址没变,指针指向的值变了.搞不懂的话自己用快递做例子) * ...
- 面试官问我:Object o = new Object() 占用了多少个字节?
小小面试一下 前言蜜语 最近马师傅火的不要不要的,虽然没有抢到耗子尾汁的商标注册权,但是必须得蹭一波马师傅的热度,下面就是闪电五连鞭的教学环节,你准备好了吗! 在正式内容开始前先甩两篇关于类加载机制和 ...
- NET 调用人脸识别算法
以前有个OpenCV 移植版EMCV可以用作图像识别等 https://github.com/emgucv/emgucv 现在有各种接口 比如虹软SDK https://ai.arcsoft.com ...
- Windows锁定屏幕然后关闭显示器,可执行程序
有时候我们需要关闭屏幕来休息一下或者在本上写东西,但是屏幕亮着的时候会分心,但是关闭显示器又太麻烦了,所以直接来一个小程序(非微信小程序).还有一种情况,有时候晚上要离开电脑旁了,但是电脑还在做事情, ...
- 怎么同步fork原git项目
如何实现 有时候,我们看到有价值的git项目,通常,我们会选择把原项目fork过来,然后自己去把玩研究.然而,原项目进行了更新,fork过来的代码却还是原来的版本,那有没有什么做法,能同时更新到我自己 ...
- 使用@Cacheable注解时,Redis连不上,直接调用方法内部的解决方案
最近redis 域名一致解析错误,导致业务多了很多异常.那么如何在这种情况下直接访问数据库,而不是报错呢 1. 解决方案 其实很简单,在配置 redis 时,只需要多一项配置,继承 CachingCo ...
- Could not open ServletContext resource [/WEB-INF/applicationContext.xml] 解决办法
Spring官方文档中规定,如果在上下文中没有指定contextConfigLoction配置文件的位置,则会默认去WEB-INF中去寻找对应的配置文件. 理论上classpath的默认路径是WEB- ...
- 听说又有兄弟因为用YYYY-MM-dd被锤了...
还记得去年分享过一篇日期格式化使用 YYYY-MM-dd 的潜在问题的文章不? 历史又重演了... 事故现场 我们来写个单元测试,重现一下这个问题. 测试逻辑: 创建两个日期格式化,一个是出问题的YY ...
- Map集合,Map常用子类
Map 集合 1,Collection中的集合,元素是孤立的,向季和忠储存的元素采用一个元素方式储存 2,Map中的集合,元素是成对存在的,每个元素中的集合称为双列集合 3,Collection中的集 ...
- ProceedingJoinPoint 某些方法记录一下
转载与百度知道,记录一下.遇到在去看API 官方文档//拦截的实体类 Object target = point.getTarget(); //拦截的方法名称 String methodName = ...