编程语言中的 DUCK TYPING|python、c++、java、go

2023-10-30 20:52

本文主要是介绍编程语言中的 DUCK TYPING|python、c++、java、go,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如果一只动物走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只动物就可以被称为鸭子。

许多编程语言都支持 Duck Typing ,通常 Duck Typing 是动态编程语言用来实现多态的一种方式。

在理解 Duck Typing 前,先看一张图片,这是曾经一度很火的大黄鸭

在这里插入图片描述

先问一个比较考三观的问题:图片中的大黄鸭,它是不是一只鸭子呢?

这个问题,得看你从哪个角度去看,如果从人们常识的认知中的角度去看,它显然不是一只鸭子,因为它连最基本的生命都没有。

但是从 Duck Typing 的角度来看,它就是一只鸭子!

Duck Typing 的原话是,走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么它就是一只鸭子。

这个原话是可以灵活理解的,就看我们怎么定义鸭子的行为,我们可以说,能浮在水上游的,黄色的,可爱的就是鸭子,那么,图片中的大黄鸭,它就是一只鸭子!

这就是所谓的 Duck Typing,它只关心事物的外部行为而非内部结构。它并不关心你这只鸭子是长肉的还是充气的。

在编程中,也常常用这种方式来描述事物。那么不同的编程语言中,Duck Typing 是怎么样实现的呢?

1. Python 中的 Duck Typing

先看一个函数:

def download(fetcher):return fetcher.get("http://xxx");

有一个 download 函数,传过来一个 fetcher 参数,fetcher 是可以获取一个 url 链接的资源的。
这个 fetcher 就是一个 Duck Typing 的对象,使用者约定好这个 fetcher 会有一个 get 函数就可以了。
显然这个 download 函数会有以下问题:

运行时才知道传入的 fetcher 有没有 get 函数。那么站在 download 函数的使用者的角度上看,我怎么知道需要给 fetcher 实现 get 方法呢?我不可能去阅读 download 函数的代码,实际情况中,可能 download 函数的代码很长,可能 fetcher 不只要实现 get 方法,还有其它方法需要实现。通常这种情况需要通过加注释来说明。

2. C++ 中的 Duck Typing

C++ 不是动态语言,但是它也能支持 Duck Typing,它是通过模板来支持的。
示例代码:

template <class F>
string download(const F& fetcher){return fetcher.get("http://xxxx")
}

这段代码与 Python 的实现方法类似,这个 fetcher 随便什么类型都可以,只要实现一个 get 方法,就能通过编译。
那么这种实现方法有什么缺点呢,就是,编译时,才知道传入的 fetcher 有没有 get 方法。
但它比 python 好一点了,python 是运行时才知道,C++ 是编译时就知道。
同样,这种情况,还是需要注释来说明。

3. Java 中的类似代码

Java 没有 Duck Typing,它只有类似的代码。Java 的 duck typing :

<F extends FetcherInterface>
String download(F fetcher){return fetcher.get("http://xxxx")
}

它同样也用了模板类型。模板 F 必须 extends FetcherInterface ,有了这个限定,就能逼着 download 函数的使用者对 fetcher 实现 get 方法,它解决了需要注释来说明的缺点。
传入的参数必须实现 FetcherInterface 接口,就没有运行时发现错误,编译时发现错误的问题。
但是,它严格上来说不是 Duck Typing 。

如果 download 函数只依赖 fetcher 的 get 方法,而 FetcherInterface 接口必须要实现除 get 方法以外,还有其它方法,那么也要一一实现,非常不灵活。

4. Go 中的 Duck Typing

在 Java 的 Duck Typing 类似代码中,如果 fetcher 参数需要同时实现两个或以上的接口方法时,Java 是没有办法做到的。但 Go 语言可以做到。

type Fetcher interface {Get(url string) string
}type Saver interface {Save(content string)
}type FetcherAndSaver interface {FetcherSaver
}func download(f Fetcher) string {return f.Get("http://xxxx")
}func save(f saver) {f.Save("some thing")
}func downloadAndSave(f FetcherAndSaver) {content := f.Get("http://xxxx")f.Save(content)
}# 实现者
type MyFetcherAndSaver struct {}func (f MyFetcherAndSaver) Get(url string) string {...
}func (f MyFetcherAndSaver) Save(content string) {...
}func main() {f := MyFetcherAndSaver{}download(f)save(f)downloadAndSave(f)
}

这里定义了三个接口,只要有 Get 方法的就是 Fetcher,只要有 Save 方法的就是 Saver,同时有 Get 方法和 Save 方法就是 FetcherAndSaver 。

实现者 MyFetcherAndSaver 并不需要声明它实现了哪些接口,只要它有相关接口的所定义的方法,那么它的实例,就即能作为 Fetcher 接口来使用,又能作为 Saver 接口来使用,也能作为 FetcherAndSaver 接口来使用。

Go 的实现方法相对比较灵活,又不失类型检查。总的来说,特点有:

  1. 即能同时实现多个接口
  2. 又具有 python , C++ 的 Duck Typing 灵活性
  3. 又具有 java 的类型检查。

转载来源:
https://segmentfault.com/a/1190000019607240

这篇关于编程语言中的 DUCK TYPING|python、c++、java、go的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/310534

相关文章

Spring Security常见问题及解决方案

《SpringSecurity常见问题及解决方案》SpringSecurity是Spring生态的安全框架,提供认证、授权及攻击防护,支持JWT、OAuth2集成,适用于保护Spring应用,需配置... 目录Spring Security 简介Spring Security 核心概念1. ​Securit

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

SpringBoot改造MCP服务器的详细说明(StreamableHTTP 类型)

《SpringBoot改造MCP服务器的详细说明(StreamableHTTP类型)》本文介绍了SpringBoot如何实现MCPStreamableHTTP服务器,并且使用CherryStudio... 目录SpringBoot改造MCP服务器(StreamableHTTP)1 项目说明2 使用说明2.1

spring中的@MapperScan注解属性解析

《spring中的@MapperScan注解属性解析》@MapperScan是Spring集成MyBatis时自动扫描Mapper接口的注解,简化配置并支持多数据源,通过属性控制扫描路径和过滤条件,利... 目录一、核心功能与作用二、注解属性解析三、底层实现原理四、使用场景与最佳实践五、注意事项与常见问题六

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

Java中Arrays类和Collections类常用方法示例详解

《Java中Arrays类和Collections类常用方法示例详解》本文总结了Java中Arrays和Collections类的常用方法,涵盖数组填充、排序、搜索、复制、列表转换等操作,帮助开发者高... 目录Arrays.fill()相关用法Arrays.toString()Arrays.sort()A

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter