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

article/2025/11/10 20:04:47

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

许多编程语言都支持 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


http://chatgpt.dhexx.cn/article/mDjqhu2G.shtml

相关文章

Windows中采用命令行方式启动服务

1. 服务名不一定是你在服务面板看到的那个名&#xff0c;例如&#xff0c;你要打开被禁用的telnet服务&#xff0c;sc config telnet start auto,报错&#xff1a;[SC] OpenService FAILED 1060&#xff0c;因为telnet的服务名不是telnet而是tlntsvr, sc config tlntsvr start …

CentOS开启服务命令详解

一、学前须知 讲服务管理之前先了解下Linux的启动流程非常有必要&#xff0c;直观的先上CentOS的启动图&#xff1a; Centos7 Centos6的也补充下&#xff1a; 图片信息量较大&#xff0c;网友可根据自己的知识水平逐一按上图去填充自己&#xff0c;也欢迎指正&#xff1b;本节…

启动consul服务命令

启动Consul 安装配置好Consul以后&#xff0c;我们可以通过简单的命令启动consul。先来看最简单的启动方式&#xff1a; consul agent -dev 在新终端中&#xff0c;执行如上操作。 hongweiyulocalhost:~$ consul agent -dev > Starting Consul agent... > Consul agen…

Windows 服务快捷启动命令

Windows 服务快捷启动命令 gpedit.msc&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;组策略sndrec32&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;录音机nslookup&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d; ip地址侦测器…

Linux 系统启动与服务管理

文章目录 1. 前言2. Linux 系统启动过程2.1 开机自检2.2 MBR 引导2.3 GRUB 菜单2.4 加载 Linux 内核2.5 init 进程初始化2.6 系统启动过程总结 3. init 进程与 systemd3.1 init 进程3.2 Centos5/6/7 init 进程对比3.3 systemd3.4 systemd 单元类型3.5 运行级别对应的 systemd 目…

linux启动服务

查看开机启动项 1&#xff1a;systemctl list-unit-files --typeservice 2&#xff1a;systemctl list-unit-files --typeservice | grep enabled 3&#xff1a;systemctl list-unit-files --typeservice | grep disabled 开机停止某个服务&#xff1a; 1&#xff1a;sudo …

Linux常用启动服务命令

一、Nginx 1、启动 [root172 udm-web]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf2、重新加载配置文件 [root172 udm-web]# /usr/local/nginx/sbin/nginx -s reload二、防火墙 1、查看状态 systemctl status firewalld2、关闭防火墙 systemc…

Windows 启动服务命令大全

描述&#xff1a; 在日常工作学习中&#xff0c;可能会常用到windows系统自带的计算器、记事本、画图等小工具&#xff0c;本文将介绍如何使用命令快速打开这些小工具。 1、快速启动画图工具 在以下三个地方输入画图工具命令&#xff1a;mspaint &#xff0c;然后按“Enter”或…

Ubuntu常用终端命令

Ubuntu常用终端命令 1.显示任务管理器&#xff1a; ps aux 2.kill进程&#xff1a; kill PID号 3.后台运行程序&#xff1a; nohup python3 xxxx.py & 4.查看文件列表 ls 5.进入文件夹 cd 文件夹名 6.解压与压缩命令 6.1.tar 文件 # 打包&#xff0c;非压缩 tar…

ubuntu在终端中打开文件管理器

打开ubuntu的终端&#xff0c;输入nautilus [path] 弹出资源管理器界面

UBUNTU 18.04开机自启动脚本实现--打开终端、执行命令及终端输入文字

开机自启动 方法很多&#xff0c;测试了一下&#xff0c;在18.04中最方便的方法如下&#xff1a; 新建sh脚本 touch xxx.sh gedit xxx.h然后输入&#xff1a; #!/bin/bash## xxx.sh## 你的代码#exit 0保存后退出&#xff0c;并在终端继续执行&#xff1a; chmod ax xxx.sh通…

Ubuntu终端打开文件及查看目录

方法/步骤 1 ctrlaltt&#xff0c;调出终端。------------ 要去某个目录&#xff0c;用cd 例如&#xff1a; cd /home/yang/下载/ 在视图中&#xff0c;后面还有一个文件夹&#xff0c;我记不住&#xff0c;就按tab键一下。就自动出来了。 如果该文件夹下东西比较多&#x…

解决Ubuntu新装系统终端打不开

一、问题说明 笔者新安装的虚拟机&#xff0c;操作系统为Ubuntu18.10&#xff0c;出现终端打不开的情况&#xff1a;应用–终端打不开&#xff0c;ctrlaltt没反应&#xff0c;进入文件管理器&#xff0c;右键–在终端中打开也没反应。 二、解决方法 进入设置&#xff0c;找到…

Ubuntu 打开多个终端

Ctrl Shift T,一个终端开启多个小终端 Ctrl Alt T 开启多个独立终端 Ctrl Shift 加号&#xff0c;放大终端字体 Ctrl 减号&#xff0c;缩小终端字体

ubuntu打开linux,ubuntu怎样打开终端(方法5种)

虽然这不是一编技术经验&#xff0c;但是想起来小编刚接触ubuntu的时候也不会打开终端&#xff0c;所以今天小编就给一些玩ubuntu的新手们&#xff0c;分享一下经验。 怎样打开终端 (方法1) 1 首先在桌面任意空白处&#xff0c;按CTRLALTT 2 这时就弹出终端窗口 (呵呵这招最好用…

Ubuntu20.04 终端打开不了的问题排查

Ubuntu20.04 终端打开不了的问题排查 今天用virtualbox安装了ubuntu20.04 问题&#xff1a;右键打开终端&#xff0c;怎么也打开不了&#xff01; 点了也没反应&#xff0c;或者鼠标转小圈圈&#xff0c;然后也没有反应… 解决方法&#xff1a; 1、Ctrl Alt F6 先切换到终…

ubuntu开机自动打开终端输入命令且执行命令

打开终端 输入 gedit ~/.bashrc打开 .bashrc文件 之后把要执行的命令写入文件末尾 保存退出 source ~/.bashrc更新文件 此时&#xff0c;打开终端后&#xff0c;就会自动执行命令 如果有sudo命令需要运行&#xff0c;则使用echo 输入密码。 比如&#xff1a;echo “passwor…

【Linux】ubuntu 20无法打开终端的解决方法

前因&#xff1a; 我在开发板Firefly上&#xff0c;用的是ubuntu操作系统&#xff0c;因其本身默认是英文输入法&#xff0c;没有中文输入法。所以&#xff0c;我安装了中文输入法&#xff0c;结果安装好了后&#xff0c;发现终端已经打不开了。。。。。。 无论是右键、单击程…

如何在Ubuntu中用终端打开pycharm

首先得知道你把pycharm放在哪个文件夹里了&#xff0c;我这里是直接在桌面创建了一个Application文件夹专门存放软件包&#xff0c;下载的pycharm包就存放在这里。 找到路径后进入bin文件夹&#xff0c;里面有一个pycharm.sh文件&#xff0c;你直接双击是没有用的&#xff0c;这…

ubuntu打开终端命令行的三种方法

一&#xff0c;简介 本文主要介绍&#xff0c;vmware虚拟机中打开终端命令行的方法&#xff0c;供参考。 二&#xff0c;操作方法 2.1 方法一&#xff1a;右键打开 2.2 点击开始按键&#xff1a; 2.3 使用快捷键“CTRLALTT” 三&#xff0c;总结 本文主要介绍3种打开终端命…