Go语言学习笔记十--面向接口 - Go语言中文社区

Go语言学习笔记十--面向接口


duck typing概念

大黄鸭

要理解duck typing的概念,先问一个问题.上图是不是一个鸭子?

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试(见下面的“历史”章节),“鸭子测试”可以这样表述:

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”[1][2]
在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

鸭子类型通常得益于"不"测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。
–维基百科

看到这个问题,肯定很多人都已经晕了,这是什么问题?第一反应有人会觉得这是个鸭子,而有人觉得它不是.类似这样的问题,就是duck typing的概念的起因.像不像是由观察者决定.

Python与C++中duck typing

在Python,C++中,支持duck typing,也就是方法中泛型变量调用的方法是否存在,只有在编译(C++)或者运行时(Python)才知道.这种灵活性带来了很大的便利,但是有一个致命的问题,编写代码时,没有提示.只能通过注释的手段提醒实现者,必须实现那些方法

Java没有duck typing

因为之前是主用Java,所以对于duck typing,没有概念,这里也搞了很久,只能说大致明白.在Java中不可能存在一个泛型调用其泛型内,没有定义的方法.如果需要调用方法必须使用继承泛型形式,<T extend Parent>,且在自定义类Parent中必须有getName(),这个方法时,T泛型才可以使用用getName方法.

所以Java通过强限制的方法,使得在编写代码时就提醒实现接口者,必须实现那些接口中方法.所以做到编辑器提醒,但是却又不够灵活.

不够灵活的原因,实现者强关联接口,接口有一点小的变动,所有的实现者都需要更改,非常麻烦.所以我们可以发现,Java中List接口为什么到了Jav8才敢动,因为使用List排序是一个很常见的需求,一直没有动的原因,就是只要一动就会牵扯到非常多的系统.

Java8中解决方案是,增加关键字default,在接口中使用default关键字修饰的方法,称为默认方法,可以在方法内些逻辑,在接口中定义方法.但是还是有些不妥,因为Java中接口是多继承的形式,那么多个接口中相同名称的default方法又会覆盖混淆.

GO语言中没有duck typing?

严格来说GO语言中是没有duck typing的,因为GO是基于结构化接口,当然这个结构化接口我还不是很懂.

但是从另一方面,以上两个接口的痛点出发,我们看一下GO语言是如何解决这两个问题的.

总结Python与C++,Java 中duck typing的缺点:

  • Python与C++灵活,但是只能通过注释方式,提醒实现者所需实现的接口
  • Java中严格,没有duck typing,编辑器会报错

GO语言解决方法:

使用者定义接口,接口的实现是隐式的,只需要实现接口里的方法即可.也就是说只要一个结构体内有与另一个接口一样的方法(参数与返回值类型相同)就认为其实现该接口,在代码上没有交集.


作者所有的学习源码在 go学习源码github地址,如果觉得有用的话帮小智贡献一个star?

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/cdzjava/article/details/87187008
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 00:08:05
  • 阅读 ( 1082 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢