QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

F#中的静态 Duck Typing

  • 2009-06-15
  • 本文字数:1339 字

    阅读完需:约 4 分钟

Duck Typing 是动态语言的重要特性之一,据Wikipedia 中的定义,这个名称及概念由 James Whitcomb Riley 提出:

当一只鸟走路像鸭子,游泳像鸭子,叫起来也像鸭子,那么我们就认为它就是鸭子。

对于传统的静态类型的语言(如 C#或 Java),类型的判定会在编译期进行,如果一系列类型需要对外界释放出某种共同的行为,那么它们则必须符合一个共同的协议(如基类或接口)。在支持 Duck Typing 的语言(如 JavaScript 或 Python)中,对于某个对象成员的访问会在运行时进行检查,正所谓“延迟判定”。关于 Duck Typing 的优劣,动态检查和静态检查之间的讨论已经数不胜数。

如果在 C#等静态语言中希望实现 Duck Typing 一般都会借助反射或动态生成适配器的方式进行,而在C# 4.0 中甚至增加了 dynamic 关键字从语法层面实现了 Duck Typing。不过在 F#中实现了一种在编译期进行检查的 Duck Typing 特性。 Matthew Podwysocki 在他的文章中展示了这样一个例子:

复制代码
<span>let inline </span>flyAndWalk arg =
<span>let </span>flying = ( ^a : (<span>member </span>Fly : unit <span>-> </span>string) arg)
<span>let </span>walking = ( ^a : (<span>member </span>Walk : unit <span>-> </span>string) arg)
(flying, walking)
<span>type </span>Duck() =
<span>member </span>this.Swim() = <span>"paddling"
</span><span>member </span>this.Fly() = <span>"flapping"
</span><span>member </span>this.Walk() = <span>"waddling"
</span><span>type </span>Eagle() =
<span>member </span>this.Fly() = <span>"soaring"
</span><span>member </span>this.Walk() = <span>"creeping"
</span><span>let </span>(eFly, eWalk) = flyAndWalk (<span>new </span>Eagle())
<span>let </span>(dFly, dWalk) = flyAndWalk (<span>new </span>Duck())

在以上代码中,flyAndWalk 方法限制了 arg 参数所必须具备的条件:“拥有特定签名的 Fly 和 Walk 方法”,而编译器则会对 flyAndWalk 方法的使用进行校验。F#提供了 inline 关键字使一个函数在编译时内联至调用方,不过它也限制了此类方法被.NET 平台上的其他语言调用。此外,与“范型”在运行时生成新类型的方式有所不同,“^”符号表示在编译期对可变类型进行静态解析。有关 inline 和“^”符号的含义及作用, Michael Giagnocavo 文章对此有较为详细的解释及相关示例。

F#的强类型 Duck Typing 特性在编译期限制了可用类型的结构,在保证了类型安全的同时,避免使用特定的协议来强制约束不同的类型。在 OCaml、Scala 等语言中,类似的特性也被称作 Structure Typing。 Lmeyerov 认为

Duck typing 看上去包含了动态的含义,而 Structure subtyping 是 Ocaml 静态世界中的瑰宝。

laogao 也有类似的看法:

我觉得严格意义上我们不应该称其为 duck typing,而是用 structural typing,只是在跟别人解释的时候,也许可以说它类似动态语言如 Python、Ruby、Groovy 等中的 duck typing 的概念。“duck typing”这个概念还是留给动态语言吧,让它指代在运行期而非编译期对类型的判定,静态语言如 Scala,还是叫“structural typing”吧。

您会在什么情况下使用这个特性呢?F#作为集成至 VS 2010 中的一线语言,已经展现出越来越强的生命力,您准备好了吗?

2009-06-15 22:451499
用户头像

发布了 157 篇内容, 共 55.6 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

《前端实战总结》之使用CSS3实现酷炫的3D旋转透视

徐小夕

css3 大前端 CSS小技巧

架构师训练营第二周框架设计课后练习

Geek_xq

程序员的故事

Philips

敏捷开发 快速开发 原创小说 企业开发 企业应用

已拿腾讯后台开发岗offer,简单说下自己的面试经历和学习路线

程序员小灰

c++ 后台开发 架构师 TCP/IP Linux服务器开发

讲述我在阿里六面的经历,幸好我掌握了这份“Java并发编程+面试题库”成功拿到20K的offer

比伯

Java 编程 架构 面试 计算机

一个真正0基础小白学习前端开发的心路历程

华为云开发者联盟

开发 开发小白 0基础

新闻|Babelfish使PostgreSQL直接兼容SQL Server应用程序

PostgreSQLChina

数据库 postgresql 开源

想了解任务型对话机器人,我们先从自然语言理解聊起

华为云开发者联盟

人工智能 机器人 自然语言

接口测试怎么进行,如何做好接口测试

测试人生路

软件测试 接口测试

《迅雷链精品课》第十课:共识算法理论基础

迅雷链

区块链

训练营第七周总结

大脸猫

极客大学架构师训练营

看区块链如何打通信息壁垒,盘活万亿级”积分”市场

CECBC

区块链 信息

我对业务方提出需求的态度

boshi

随笔杂谈 需求落地

每周学点TARS——服务自定义命令

TARS基金会

c++ DevOps 后端 TARS

一周信创舆情观察(11.23~11.29)

统小信uos

ONES 收购 Tower,五源资本合伙人对话两位创始人

万事ONES

项目管理 团队协作 ONES Tower 收购

训练营第七周作业

大脸猫

极客大学架构师训练营

技巧收藏|10个JavaScript常用数组操作方法

华为云开发者联盟

Java 数组 开发

「更高更快更稳」,看阿里巴巴如何修炼容器服务「内外功」

阿里巴巴云原生

容器 运维 云原生 双十一 CloudNative

架构师训练营 1 期 -- 第十一周总结

曾彪彪

极客大学架构师训练营

mysql的这些坑你踩过吗?快来看看怎么优化mysql?

比伯

Java 编程 架构 面试 计算机

打造Django私有化缓存组件django-api-cache

pygodnet

django django-api-cache django缓存 私有化缓存 接口缓存

价值、产业、数据加密,区块链如何助力互联网升级?

CECBC

区块链 互联网

线程池的优点及其原理,代码实现线程池。简单、明了。

Linux服务器开发

后端 网络编程 线程池 Linux服务器 web服务器

区块链产业下的“非遗”突围战:商业化和手艺人发掘

CECBC

区块链 非遗

性能压测

jorden wang

挑战赛 | 话题王者VS互动先锋(第一季)

InfoQ写作社区官方

话题讨论 热门活动

年轻人想详细了解做了十年Linux跟做了十年Windows的程序员差距有多大吗?听我慢慢道来!

ShenDu_Linux

Linux 程序员 windows

我在阿里巴巴做 Serverless 云研发平台

阿里巴巴云原生

Serverless 容器 开发者 云原生 CloudNative

即使不会node.js,拖拽就可完成数据的可视化展示

华为云开发者联盟

node.js 数据 可视化

ONES 收购知名协作工具 Tower

万事ONES

团队协作 高效 研发管理工具 收购 资讯

F#中的静态Duck Typing_.NET_赵劼_InfoQ精选文章