「當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。」


簡單來說,假設有一隻鳥,他會游泳、會叫,而我們定義的鴨子需要會游泳、會叫,就可以說那隻鳥是鴨子,即使它可能是一隻企鵝。

我們並不在乎他是否繼承自鴨子的血緣,到底是不是鴨子,只在乎他的「行為」。

比如在 Ruby 等程式語言中,有中括號 [ ] 取值的方法,除了陣列以外,字串、Hash 等物件都可以使用,甚至是在自訂的 class 中寫入中括號的方法,不管它的型別是什麼,只要具備中括號的方法,就可以使用。


以下的範例體現了鴨子測試,只要有 quack, feathers 方法,對 in_the_forest 函式而言,該物件就是一個鴨子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Duck
def quack
puts "這鴨子正在嘎嘎叫"
end

def feathers
puts "這鴨子擁有白色和灰色的羽毛"
end
end


class Person
def quack
puts "這人正在模仿鴨子"
end

def feathers
puts "這人在地上拿起1根羽毛然後给其他人看"
end
end


def in_the_forest(duck)
duck.quack
duck.feathers
end


def game
duck = Duck.new
person = Person.new
in_the_forest(duck)
in_the_forest(person)
end


game

# 這鴨子正在嘎嘎叫
# 這鴨子擁有白色和灰色的羽毛
# 這人正在模仿鴨子
# 這人在地上拿起1根羽毛然後给其他人看

只是,由於鴨子型別所帶來的方便與靈活度,也可能早成難以檢測的錯誤,開發者需注意不同類別中相同方法的可能使用。


參考資料
https://zh.wikipedia.org/wiki/%E9%B8%AD%E5%AD%90%E7%B1%BB%E5%9E%8B