少用繼承,多用介面

閱讀時間約 6 分鐘

承接上一篇文章,現代的物件導向已經走偏了,他就像null pointer,很容易出現不好的設計。自從我深入學習函數式編程後,漸漸發現物件導向的不合理的設計,而學習rust之後更讓我開始討厭物件導向,rust幾乎把所有我認為不好的地方都修正了。這個系列的文章我將會一一比較物件導向與rust的差異。這篇文章將關注於繼承機制。


物件導向的設計方式通常是先預想多個任務或情境,並設計一個物件來統一處理它,之後若是有新的情境,可以藉由繼承來延伸功能。這種設計方式好處是非常直觀且容易擴展,但這反而容易累積各種技術債。設計物件時一般都是以可擴展為前提,但我們往往無法預測它會怎麼擴展,有可能之後的擴展打破了一些原本的假設,使得之前寫的程式邏輯出現錯誤。這種「向後的抽象化設計」很容易出現這種情況,因為我們總是以「這部分的程式碼可以重用」來實作父類別,但並沒有考慮到應該在怎樣的情況下才能使用。正確的設計方式應該要寫明繼承這個類別應該符合哪些規則,也就是關注約束(constraint)而非延展(extension)。抽象化就是對未知的事物建立模型,這個過程很容易會將先入為主的假設帶入其中,而關注約束更容易發現那些未察覺的潛在資訊(unknown knowns),讓你更能夠意識到你的程式邏輯運用了哪些假設。


這種關注約束的設計方式更適合使用介面而非類別來定義規則,尤其是當你想要抽象化的行為不侷限於一種類別時。例如,當你想要設計一個可以連線的物件,但又不想限制在某種情境下運作,你應該設計一個介面Connectable而非抽象類別Connection。介面一般不帶有預設實作,因此本身並不具有重用程式碼的能力。若是要重用程式碼,不應依賴於繼承機制,而是使用高階函式或是組合物件等方法,如此更容易把規則理清。除去延伸功能後,繼承仍可以用來細分類別,也就是讓物件在已知的情境下做出不同的行為,而這個機制應當只在內部使用,不應讓它在你不知道的地方被繼承改寫。


rust的trait system類似於介面,但並不完全一樣。trait(特性)跟介面一樣都是用於描述行為,也一樣都是關注於約束而非延展。實作介面一般需要在定義類別時實作介面的方法,也就是介面是類別的一部分。而trait描述的是特性本身,並不需要在定義類別時實作。trait所描述的特性並不侷限於單個類別,它也可以描述多個類別之間的特性,例如A: Add<B>描述的是A與B之間的加法關係。rust甚至可以為符合某些條件的所有類別實作trait,例如我們可以為所有擁有特性A: Add<A> 的類別A實作A: Mul<uint>。基於以上能力,我們不應該把trait當作類別的一部分,而是特性本身。然而rust把trait的語法設計的跟介面一樣,其實它應該寫作Add<A,B>,也就是「存在一個trait描述A與B之間的加法特性」,編譯器會根據上下文去搜尋合適的trait。trait 的這種設計把類別的定義與trait的定義分開,讓我們可以把不同的關注點分離開來,而非像介面必須綁在類別的定義之上。


rust跟物件導向的另一個很大的不同是rust沒有類似於繼承的子類關係,但是有基於泛型的子類關係。在有繼承特性的程式語言中,當你拿到了一個類別為A的參數,它可能其實是B的物件實體,只是它的類別繼承自A。這種子類關係使得類別無法描述實際的物件實體,迫使我們必須以抽象的方式思考程式邏輯,而非基於實作細節。這種隱藏部分細節的做法讓我們能夠把雜音去除,讓我們專注於更重要的概念與程式邏輯。然而我們沒辦法限制變數只能是哪種實體,有些程式語言甚至沒辦法阻止類別被繼承,就算能也不適用於所有情況,這使得我們需要額外注意上下文才能判斷變數到底是不是延展過的物件。


基於泛型的子類關係則是利用類型參數與類型約束界定類別的範圍,例如List<A> where A: Comparable 代表由所有內容可比較的列表的集合,也就是List<int>, List<string>, List<List<int>> 等類別的聯集(正確來說是indexed family)。他的子類關係建立在約束的強度,例如它是 List<A> where A: Equal 的子類,因為所有可比較的類型都是可以判斷相等的,因此其組成的列表也有子類關係。類型參數明確地表明我們不知道它到底是什麼,只知道它有什麼特性,因此更能區別抽象與實作的邊界。你可以把類型參數想像成某個類別「未知」的部分,比起宣告x: List<Comparable>(變數x是內容可以比較的列表,但我不知道他的內容到底是什麼),不如宣告A: Comparable跟x: List<A>(變數x是內容可以比較的列表,但我不知道他的內容到底是什麼,姑且叫他A)。透過泛型,我們可以把未知的部分串聯起來,並使程式邏輯更加一致。


rust的trait在意義上跟類型有很大的不同,他更像是類型的種類而非一種特殊的類型,因此不能直接宣告變數為 Comparable,必須藉由類型參數的約束描述物件的抽象行為。因此trait用來描述抽象的概念,而型別則用於描述實際的資料結構。這一點跟介面很不一樣,我們一般都會把介面當作一種純抽象類別,因而用類似繼承的概念思考。在trait system中,A: Comparable代表的不是「類型A是類型Comparable的子類」,而是類型本身是Comparable裡的一個類別。Comparable可以看作是類別的集合,而我們透過這些集合界定我們想要的類型,就像是我們可以透過類型界定我們想要的物件,因此trait被稱為二階類型(2-types, kinds)。正因為它們不是包含關係(⊆)而是隸屬關係(∈),抽象的概念才能完全從類別獨立出來。

4會員
28內容數
這不是教你如何從物件導向到函數式編程的入門教程。我會深入探討物件導向與函數式編程的差異,並討論為什麼你應該使用函數式編程並徹底放棄物件導向。
留言0
查看全部
發表第一個留言支持創作者!
have bear的沙龍 的其他內容
在現代,物件導向雖然仍是主流,函數式慢慢得到關注。物件導向並不適合所有的程式邏輯,但在像是Java的物件導向的程式語言中,幾乎所有值都被當作物件,因此在一些情境下Java寫起來會非常冗余。物件導向流行的原因大概是因為它的思考方式比較符合我們對於世界的認知,但邏輯推理與解決問題的方式卻不一定符合我們的
我學習程式語言的動機並不是想要做什麼遊戲,而是單純覺得很有趣。除去國小自己寫過網頁的經歷,我
What Color is Your Function? 一文中 Async function 被比喻成「紅色函式」 紅色函式不能在普通的函式裡(即「藍色函式」)使用 因此紅色具有感染性 定義函式之前必須先決定是否要染成紅色 作者不喜歡這種麻煩的規則 但我認為這種麻煩是有道理的
'方格子在 linux/firefox 上的 bug 超煩 '若在每行第一句打中文會被吃掉 'Ctrl+V還會複製貼上之後的文字貼上之後的文字
在現代,物件導向雖然仍是主流,函數式慢慢得到關注。物件導向並不適合所有的程式邏輯,但在像是Java的物件導向的程式語言中,幾乎所有值都被當作物件,因此在一些情境下Java寫起來會非常冗余。物件導向流行的原因大概是因為它的思考方式比較符合我們對於世界的認知,但邏輯推理與解決問題的方式卻不一定符合我們的
我學習程式語言的動機並不是想要做什麼遊戲,而是單純覺得很有趣。除去國小自己寫過網頁的經歷,我
What Color is Your Function? 一文中 Async function 被比喻成「紅色函式」 紅色函式不能在普通的函式裡(即「藍色函式」)使用 因此紅色具有感染性 定義函式之前必須先決定是否要染成紅色 作者不喜歡這種麻煩的規則 但我認為這種麻煩是有道理的
'方格子在 linux/firefox 上的 bug 超煩 '若在每行第一句打中文會被吃掉 'Ctrl+V還會複製貼上之後的文字貼上之後的文字
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
可能包含敏感內容
5W是大家很常會用到的方式 之前有一篇有提到 問題分析跟職能的大小T很像 使用樹狀圖的What、Why、How三個層級 也提到Why、Why、Why的方式來深入探討問題 但是 在運用上還是要看問題狀況還選擇 Why偏向於找出過去發生的原因 How偏向於找出未來處理的方法 兩個是不同
Thumbnail
【記者許家源/雙北報導】        臺北市青少年發展暨家庭教育中心響應10月10日世界心理健康日,於10月14日(星期六)與中華心理衛生協會合作辦理「兒少心理韌性書目發布會」暨書展,當天將進行年度推薦書目發布,並設有心理韌性圖書閱讀區,也邀請不同學校至現場進行心閱讀校園方案展示,歡迎各界踴躍參
Thumbnail
❤️粉紅泡泡!讓我們為【初戀】買單! 回頭梳理這段筆記,他和我那幾年都處在【人生最低谷】,初戀被【現實面】上,重重地打臉!粉紅泡泡讓我們,都為自己的初戀,狠狠地買單!但是,你說再來一次,小倉鼠會如何選擇?我會說,【高中姐妹淘】和【初戀】,仍然會是我的優先順位,因為,一直到現在,我還是很感謝自己有過,
Thumbnail
❤️閱讀之後,如何化【知道】為【做到】呢? 這次挑了這本《少就是力量》,其實,這本書從買回家,反反覆覆被我看了好多次,反覆看原因是我內心一直有想培養的習慣,但是,想馬上養成並不容易,剛開始以為這一本斷捨離的書,可以協助解決內心的困擾,後來發現減法的道理,套在看待人生也是可以,但是,人生就是這樣,很多
Thumbnail
產品規劃流程時,除了要思考如何優化使用者體驗,也要思考如何減少用戶阻力,讓用戶在最「簡單、快速」的情境下完成任務,這篇想整理我看的到減少用戶阻力的方法。
Thumbnail
聖誕節到了,三個小孩仍然非常重視這節日,尤其是那份由聖誕老人送出的聖誕禮物。記得初到台灣時,天一在聖誕節一起床發現不見聖誕禮物而大哭,最後在放衣服的房間中找到禮物才破涕為笑。又有一年孩子在餐桌上放滿糖果,又在地方灑上米,希望能捕捉聖誕老人的足跡,現在回想仍覺得好好笑。今年比較小的兩位孩子趕在聖誕節前
Thumbnail
遠離手機、電腦,特別特別是社交媒體的一天有撐下去嗎?|有夢的人,承受挫折的時候,也要好好的跟自己說一聲:「辛苦了!」
Thumbnail
根據衛生福利部統計,民國108年有10萬3,930人被通報家暴,平均每5分鐘就有1人遭受家暴,估計一年有15萬名孩子在傷痛中長大。春節年假將至,家屬接觸機會頻繁,現代婦女基金會憂心家暴發生率提高,特於農曆春節前辦理「我的小角落」─用愛守護公益展,期待增進民眾對家庭暴力的影響及求助
Thumbnail
缺水的根本,應該不是用了多少水,而是雨下不來。 為什麼雨總是下不來?我想你們應該知道答案!
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
可能包含敏感內容
5W是大家很常會用到的方式 之前有一篇有提到 問題分析跟職能的大小T很像 使用樹狀圖的What、Why、How三個層級 也提到Why、Why、Why的方式來深入探討問題 但是 在運用上還是要看問題狀況還選擇 Why偏向於找出過去發生的原因 How偏向於找出未來處理的方法 兩個是不同
Thumbnail
【記者許家源/雙北報導】        臺北市青少年發展暨家庭教育中心響應10月10日世界心理健康日,於10月14日(星期六)與中華心理衛生協會合作辦理「兒少心理韌性書目發布會」暨書展,當天將進行年度推薦書目發布,並設有心理韌性圖書閱讀區,也邀請不同學校至現場進行心閱讀校園方案展示,歡迎各界踴躍參
Thumbnail
❤️粉紅泡泡!讓我們為【初戀】買單! 回頭梳理這段筆記,他和我那幾年都處在【人生最低谷】,初戀被【現實面】上,重重地打臉!粉紅泡泡讓我們,都為自己的初戀,狠狠地買單!但是,你說再來一次,小倉鼠會如何選擇?我會說,【高中姐妹淘】和【初戀】,仍然會是我的優先順位,因為,一直到現在,我還是很感謝自己有過,
Thumbnail
❤️閱讀之後,如何化【知道】為【做到】呢? 這次挑了這本《少就是力量》,其實,這本書從買回家,反反覆覆被我看了好多次,反覆看原因是我內心一直有想培養的習慣,但是,想馬上養成並不容易,剛開始以為這一本斷捨離的書,可以協助解決內心的困擾,後來發現減法的道理,套在看待人生也是可以,但是,人生就是這樣,很多
Thumbnail
產品規劃流程時,除了要思考如何優化使用者體驗,也要思考如何減少用戶阻力,讓用戶在最「簡單、快速」的情境下完成任務,這篇想整理我看的到減少用戶阻力的方法。
Thumbnail
聖誕節到了,三個小孩仍然非常重視這節日,尤其是那份由聖誕老人送出的聖誕禮物。記得初到台灣時,天一在聖誕節一起床發現不見聖誕禮物而大哭,最後在放衣服的房間中找到禮物才破涕為笑。又有一年孩子在餐桌上放滿糖果,又在地方灑上米,希望能捕捉聖誕老人的足跡,現在回想仍覺得好好笑。今年比較小的兩位孩子趕在聖誕節前
Thumbnail
遠離手機、電腦,特別特別是社交媒體的一天有撐下去嗎?|有夢的人,承受挫折的時候,也要好好的跟自己說一聲:「辛苦了!」
Thumbnail
根據衛生福利部統計,民國108年有10萬3,930人被通報家暴,平均每5分鐘就有1人遭受家暴,估計一年有15萬名孩子在傷痛中長大。春節年假將至,家屬接觸機會頻繁,現代婦女基金會憂心家暴發生率提高,特於農曆春節前辦理「我的小角落」─用愛守護公益展,期待增進民眾對家庭暴力的影響及求助
Thumbnail
缺水的根本,應該不是用了多少水,而是雨下不來。 為什麼雨總是下不來?我想你們應該知道答案!