繼承 <> D 的意志!鐵拳卡普、革命家龍、草帽魯夫,這一家真的沒開外掛嗎?

https://ithelp.ithome.com.tw/upload/images/20200920/20128363OKSPnJlEte.jpg

[Day11] 由左至右:海賊五皇魯夫、革命軍首領龍、海軍英雄卡普,這祖孫三代的組合會不會太強。。。

繼承

在 Ruby 裡,上下層的類別之間會有**繼承(inheritance)**關係,那麼,什麼是繼承關係呢?

繼承就是你老爸超有錢叫你不用去工作了(誤)
咳咳。。。我想一般人都沒有這種老爸,

我們先看一張國小自然課本裡的圖片好了,大家還記得林奈嗎?
https://ithelp.ithome.com.tw/upload/images/20200920/20128363M0s2bnw1MX.jpg
看出生物學家都是整理控了嗎?

覺得頭大?還是我找法律條文裡的繼承會不會好一點?(討打)
畢竟地球上的生物有百百種,因此如果不按照物種「共有的生理特徵」進行分類,怎麼知道哪一些生物的關係比較接近呢?(不知道好像也沒關係

而 Ruby 裡的繼承關係也是一樣的,在 Ruby Guide 的文件裡有介紹到繼承的概念,簡而言之就是每個類別向上都還有自己所屬的類別。

舉個例子,譬如蘋果柳橙各是一種水果,水果又是食物的一種:

1
2
3
4
5
6
7
8
9
10
11
class Food
end

class Fruit < Food
end

class Orange < Fruit
end

class Apple < Fruit
end

按 1:在 Ruby 的世界裡,小於符號 「<」 被用來表示「繼承」的意思。
按 2:OrangeApple 這兩個類別都屬於 Fruit 類別,而 Fruit 類別又屬於更上層的 Food 類別。

在物件導向的概念裡,如果這些類別的用途是同一型的,譬如 OrangeApple 都很適合打成果汁(?) 通常我們會把相同功能的方法移到「上一層」的類別,所以我會在 Fruit 這個類別直接定義一個 juicy 方法

1
2
3
4
5
6
7
8
9
10
class Fruit < Food
def juicy
end
end

o1 = Orange.new
a1 = apple.new

o1.juicy
a1.juicy

然後,只要是繼承自 Fruit 的所有類別所產生的實體,都可以使用 juicy 方法。


與其說繼承,不如說這是分類吧?

因此 Ruby 語言裡的繼承,我個人認為用分類這個詞可能會更貼切,也更精準一點,不過既然前面都有這麼多大大的貼文了,就虛(ㄐ一ㄤ)心(ㄐ一ㄡ ˋ)接受這個詞吧!

再來看一些程式碼吧!

先定義一個叫 Animal 的類別,並在這個 Animal 類別裡定義了兩個實體方法::walk:eat

1
2
3
4
5
6
7
8
class Animal
def walk(place)
puts "走去 #{place}!"
end
def eat(food)
puts "#{food} 好吃!"
end
end

再讓 CatDog 類別都繼承自 Animal 類別。

1
2
3
4
5
class Cat < Animal
end

class Dog < Animal
end

CatDog 類別分別創造的實體 kittywoffy

1
2
kitty = Cat.new
woffy = Dog.new

kittywoffy 居然都能使用 Animal 類別裡的方法了,這就是繼承的概念!

1
2
3
4
5
6
7
8
9
10
11
12
13
kitty.eat("罐罐")
woffy.eat("骨頭")

# 印出
罐罐 好吃!
骨頭 好吃!

kitty.walk("教室")
woffy.walk("交誼廳")

# 印出
走去 教室!
走去 交誼廳!

有了繼承以後,我們在撰寫程式碼時,就可以不用在同類型的類別裡重複定義相同的方法,這對工程師真是一大福音啊!


我爸是我爸,但我也有自己的尊嚴!

在類別裡,如果定義了一個方法和繼承自上層類別的方法重複了,那麼在呼叫時原先繼承來的方法就會被蓋掉,優先使用自己類別寫的方法:

讓我們看個例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Father
def persist
puts "不放手直到夢想到手"
end
end

class Child < Father
def persist
puts "人生恰恰像馬拉松賽跑一樣"
end
end

daddy = Father.new
me = Child.new

daddy.persist

# 印出
不放手直到夢想到手

me.persist

# 印出
人生恰恰像馬拉松賽跑一樣

如此一來,當 me 在呼叫 persist 方法時,和 daddy 呼叫 persist 兩者得到的是不同的結果。(就算個性再像的父子,也有不同的人生哲學!)


今天就先到這邊啦!明天應該會介紹模組(Module),敬請期待!