关于鸭子类型

其实对我来说鸭子类型一直是一个比较模糊的概念,因为平常不去关注,关注的时候一般是在面试或者被面试的时候,今天在看一篇博客的时候又有看到,所以就索性弄清楚

 

``` 

首先 与duck typing相对应的是normal typing(对象的类型决定对象的特性)

*既然是相对,可以简单理解为 duck typing 就是对象的特性决定了他是什么,说一个烂大街的句子:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”,不是因为它是鸭子所以走路,游泳和叫像鸭子,而是走路,游泳和叫像鸭子所以被``认为``是鸭子

duck typing中对象的类型不重要,只要对象有类型A的方法和属性,那么它被当做类型A来使用。熟悉c的同学应该明白c就是normal typing,在编译阶段静态检查,函数定义和传参类型需要保持一致,不一致就编译报错。参数类型当然也包含了 ``对象`` 参数,后面我会举个Go的例子。
 
Python中的鸭子类型
class Duck:
  def fly(self):
    print("Duck flying")

class Airplane:
  def fly(self):
    print("Airplane flying")

class Whale:
  def swim(self):
    print("Whale swimming")


def runtest(obj): 

  obj.fly()


duck = Duck()
airplane = Airplane()
whale = Whale()

此时:
runtest(duck)        √
runtest(airplane)   √
runtest(whale)       ×

前两个有fly方法,所以在下面的runtest中直接就可以调用,runtest不去理会你传进来的到底是谁的对象,只要你有这个方法,那么我就可以去调用运行。

其实就是多态的一种体现,多态是什么?“多态是指不同类的对象对同一消息作出响应,同一个接口,不同的对象会做出不同的反应;同一个行为可以通过多种表现形式展现出来就是多态”

例如上面同样的runtest这个接口,输入了不同的对象,打印了不同的结果。
 
go语言中的函数:
package main

type st struct {
    X int
    Y int
}

type st2 struct {
    X int
    Y int
}

func FuncTest(s st) {
    s.X ++
    s.Y ++
}

func ForTest()  {
    a := st2{1,2}
    FuncTest(a)
}

这种写法最后会报如下错误:

# awesomeProject
.\fortest.go:25:10: cannot use a (type st2) as type st in argument to FuncTest

用Python来理解就是 这里的函数FuncTest入参为 st结构体 的类这个类型,这时传给它了一个 st2结构体 的类对象,函数FuncTest就会报错。

 

```

 

个人新理解:

今天(20210526)突然又想起了这个问题,静态语言会在编译时进行报错,python作为动态语言其实会在执行时进行报错,所以鸭子类型是静态语言的规则,是强制的;

而鸭子类型是动态语言的一种规范或者说风格,在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。例如python,你完全可以不去遵守类名是什么,也不用管方法里面干了什么。这就是静态语言和动态语言鸭子类型的区别吧,而同时是不是也意味着鸭子类型是个专属强类型语言的概念,对弱类型语言不适用呢?因为对弱类型语言不是很了解,暂时先提个这个设想。

 

 

知识储备有限,很可能会出现错误,欢迎指正😜

参考:

https://www.jianshu.com/p/cd06818935a8

 

posted @ 2020-05-11 17:56  seas  阅读(199)  评论(0编辑  收藏  举报