Duck typing

第一次了解到这个词汇是我在知乎提了一个问题,知乎传送地址

vczh在答案中提到了duck type,于是google了一番,大概了解了一下,附上wiki地址

在面向对象的编程语言中,所谓的duck type是指:对象的属性和方法决定了类的语义,而不是它的继承关系或者是它实现了某个接口。这个概念最早是由James Whitcomb Riley提出的,下面这句话可以帮助我们理解:

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

程序员只需要确保对象在特定的上下文中的行为符合他们的期望就可以了,而不用确保对象是某种特殊的类型。比如说,在一个none-duck-type的编程语言中,一个类的方法需要传递一个Duck类型的参数,以确保方法能正确调用参数的quack和walk方法(两个方法都是Duck类型的对象所拥有的方法)。而在一个duck-type的编程语言中,一个类的方法可以传递任意类型的参数,并且直接调用它们的quack和walk方法,如果参数没有这两个方法的话,会抛出一个运行时异常,duck-type编程语言不依赖于类型,而是依赖于文档约束、清晰的代码、以及测试来确保程序的正确性。

下面贴出一段支持duck type的伪代码:

function calculate(a, b, c) => return (a+b)*c

example1 = calculate (1, 2, 3)
example2 = calculate ([1, 2, 3], [4, 5, 6], 2)
example3 = calculate (‘apples ‘, ‘and oranges, ‘, 3)

print to_string example1
print to_string example2
print to_string example3

可以看到calculate使用的参数分别是number、list和string,三者之间毫无继承关系,只要对象支持+和*操作,calculate就能正常使用。如果将这段伪代码转换成Python、Ruby的话,会有如下的输出:

9
[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
apples and oranges, apples and oranges, apples and oranges,

从多态的角度来看,duck type跟其它none-duck-type OO语言没啥区别,都能正常工作。但是从继承的角度来看,两者是不一样的,对于none-duck-type编程语言,如果你caculate定义的参数是string类型,在调用时却传递了一个nubmer参数,编译器会报错。

下面贴一段Java代码,用于模拟duck-type:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DuckTyping {

    interface Walkable  { void walk(); }
    interface Swimmable { void swim(); }
    interface Quackable { void quack(); }

    public static void main(String[] args) {
        Duck d = new Duck();
        Person p = new Person();

        as(Walkable.class, d).walk();   //OK, duck has walk() method
        as(Swimmable.class, d).swim();  //OK, duck has swim() method
        as(Quackable.class, d).quack(); //OK, duck has quack() method

        as(Walkable.class, p).walk();   //OK, person has walk() method
        as(Swimmable.class, p).swim();  //OK, person has swim() method
        as(Quackable.class, p).quack(); //Runtime Error, person does not have quack() method
    }

    @SuppressWarnings("unchecked")
    static <T> T as(Class<T> t, final Object obj) {
        return (T) Proxy.newProxyInstance(t.getClassLoader(), new Class[] {t},
            new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    try {
                        return obj.getClass()
                            .getMethod(method.getName(), method.getParameterTypes())
                            .invoke(obj, args);
                    } catch (NoSuchMethodException nsme) {
                        throw new NoSuchMethodError(nsme.getMessage());
                    } catch (InvocationTargetException ite) {
                        throw ite.getTargetException();
                    }
                }
            });
    }
}

class Duck {
    public void walk()  {System.out.println("I‘m Duck, I can walk...");}
    public void swim()  {System.out.println("I‘m Duck, I can swim...");}
    public void quack() {System.out.println("I‘m Duck, I can quack...");}
}

class Person {
    public void walk()  {System.out.println("I‘m Person, I can walk...");}
    public void swim()  {System.out.println("I‘m Person, I can swim...");}
    public void talk()  {System.out.println("I‘m Person, I can talk...");}
}

duck-type可以这么理解:我不关系type,我只关心你有没有对应的方法,以上面的calculate方法为例,我不关心你是string、number还是list,你只要实现了+和*方法,我就能正常工作。

Duck typing,布布扣,bubuko.com

时间: 2024-08-11 23:42:13

Duck typing的相关文章

什么是鸭子类型(duck typing)

"当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子." 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为. 比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket.它们有很多相同的方法,我们把它们当作文件使用. 鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式. 下面例子用duck typing来实现多态. #coding=utf-8 class

什么是“鸭子类型(duck typing)”?

在计算机编程世界里会接触到一个知识点 —— duck typing,叫“鸭子类型”. 它有一个形象的解释: “当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子.” 怎么去理解这句话呢? 鸭子,假如我们都不知道它表示什么.我定义:会走的.会游泳的.会叫的鸟 —— 叫“鸭子”. 我定义的这个“鸭子”,可以说是一个分类,在这个分类里,都是包含了具有共同技能(走.游泳和叫)的鸟. 这个“鸭子”就属于“鸭子类型”.对于这个类型里的每一个成员(不只有“鸭子”),其分类的依

Monkey Patch/Monkey Testing/Duck Typing/Duck Test

Monkey Patch Monkey Testing Duck Typing Duck Test

【ZOJ 3480】Duck Typing

题 题意 1.有t组数据,输入时每组数据之间空格隔开,输出时也要求空格隔开. 2.每组都是一行begin开始,一行end结束. 3.class ClassName[:Super] 表示声明一个类型,Super值存在时,说明它继承Super类型. 4.def ClassName.Method 表示声明ClassName类型的一个方法. 5.undef ClassName.Method 表示删除该类型下该方法. 6.call ClassName.Method 表示调用该方法,如果该类型本身没有该方法

[模拟]ZOJ3480 Duck Typing

题意:给了一坨...按题目意思输出就好了... 给一组案例 100 begin class d class c:d class b:c class a:b def d.m def d.n call a.m end 答案应该是 class dclass c:dclass b:cclass a:b def d.m def d.n invoke d.m 建立的泪应该是这样的 a:b:c:d d有method m和n 那么call a.b.c的n.m时都应invoke d的 1 map<string,

duck type鸭子类型

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定.这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试(见下面的"历史"章节),"鸭子测试"可以这样表述: "当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子."[1][2] 在鸭子类型中,关注的不是对象的类型本

Duck Type in Python

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定 “当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子.” 就我个人的理解来看,duck type 是一种语法糖,它不强调对象的类型,或者它继承自哪里,只在乎它是否能够实现了我需要的方法,总的来说,就是,不管你什么出身,不管黑猫白猫,能抓住老鼠的就是好猫. 这种动态类型可以很方便的实现多

喜欢ruby编程语言的几个原因

Ruby编程语言是由日本人松本行弘开发,是一种简单快捷的面向对象编程语言,今天主要跟大家聊聊ruby框架--ruby on rails(http://www.maiziedu.com/course/ruby/),可能有些朋友不喜欢ruby,但是作为一门语言,我觉得 Ruby 还是很值得掌握和学习的. 先说说学好 Ruby 有什么好处吧. Ruby on Rails 的最大优势我觉得有四个: 1. 语言灵巧轻便,适合快速开发和部署. 2. 各种本身自带的 "magic" 以及可以通过 g

作为.NET程序员,您需要IronPython么?

.NET作为一个成熟的开发平台,为很多语言的发展提供了肥沃的土壤:历史相对久远的有Managed C++.C#.VB.NET.J#,正值壮年的则有IronPython.IronRuby,而老赵极力推崇的F#则是后起之秀了.面对那么多的语言,选择自然也是一个难题.在大部分开发人员眼中,C#是最为正统的.NET语言,它几乎是为.NET而生的,语言版本更替的速度与.NET Framework相比,一点都不含糊,这不,C# 4.0都出来了.因此,C#通常都是.NET开发人员的首选语言.但是,掌握了C#之