面试扣分:鸭子类型是什么?假设你今天去面试,面试官问你:“鸭子类型是什么?”。你怎么回答?当你熟悉维基百科时,脑海中闪过如下截图:图片中的红框闪电般在你脑海中闪过。你竖起中指竖起黑框眼镜,自信地说:duck类型是指函数不关心传入的参数类型,只关心这个参数对应的对象有没有methods和你想要的属性。如果有,它将起作用。如果没有,则无法运行。就像我看到一只鸟,只要它叫声像鸭子,走路像鸭子,羽毛像鸭子一样白,我就认为它是鸭子,不管它到底是什么。说完这句话,一道光芒划过你的眼镜。你心想,这就稳了。面试官又问:那你用Golang写一个duck类型的例子。仔细想想,Golang是静态语言,参数必须声明类型。如何绕过它的类型检测?你再想想,不对,Golang确实可以绕过类型检测。只需使用界面。所以你写下了一段Golang语言代码:,"Sleeping")}func(pPet)Sleep(){fmt.Println(p.name,"Sleeping")}func(pPeople)Eat(foodstring){fmt.Printf("%s正在吃%s\n",p.name,food)}func(pPet)Eat(foodstring){fmt.Printf("%siseating%s\n",p.name,food)}funccheck(animalAnimal){animal.Eat("狗狼")animal.Sleep()}funcmain(){singleDog:=People{name:"单身狗",}dog:=Pet{name:"旺财",}check(singleDog)check(dog)}代码运行效果如下图所示:然后你说明在函数main()中,变量singleDog是People类型,变量dog是Pet类型。虽然它们是不同的类型,但是由于它们都有Eat方法和Sleep方法,所以它们都可以运行在check函数中。面试官又问了,你的代码没有问题,例子也没有问题。那我再问你,既然check函数不关心传入参数的类型,只关心他们的method,那是不是意味着check函数接收到的参数是duck类型的呢?你说,是的。面试官又问了,但是我们从代码中可以看出,check函数接收到的参数animal的类型是一个接口类型。这是否意味着接口类型等于鸭子类型?你一时答不上来。面试官又问了:接口类型和鸭子类型有什么关系?duck类型是不是和int、string、map一样是内置类型?我们在Golang中可以使用varastring来声明一个string类型的变量,那么如何实现呢?声明一个鸭子类型的变量?在Golang自带的关键字中,你记不住哪个关键字包含了duck这个词。面试官摆出耐克的笑容对你说:“回家等通知吧。”这个令人讨厌的面试官的最后一个问题难倒了你。但这个问题实际上是一个陷阱。面试官给你玩了一个文字游戏。当他把duck类型和整数类型、string类型结合在一起的时候,让你觉得duck类型也是一种类型。但实际上ducktyping不是类型,ducktyping是dynamictyping的一种风格:怎么解释什么叫设计风格?以Python为例:确保传入的变量必须是特定类型,然后执行相应的方法#确保参数是特定类型,然后调用里面的方法defcheck(animal):ifisinstance(animal,pet):animal.eat()elifiisinstance(animal,People):animal.eat()else:raiseException("Typeerror!")不管传入什么类型的参数,只要有eat方法,它可以执行。如果对象没有eat方法,Python会自动抛出异常。defcheck(animal):animal.eat()在鸭子类型的设计风格中,开发者并不关心对象是什么类型。它只关心对象是否有特定的方法。总结:鸭子类型是一种设计风格,而不是一种具体的类型。本文转载自微信公众号“闻所未闻的密码”,可通过以下二维码关注。转载本文请联系Code公众号。
