靜態(tài)類型和動態(tài)類型有什么區(qū)別?

編程語言按照類型檢查可以分為兩大類:靜態(tài)類型 (Static Typing)動態(tài)類型 (Dynamic Typing)砍聊。在現(xiàn)在比較流行的這些語言里页藻,靜態(tài)類型的代表人物有 Java桨嫁、C/C++、Golang 等份帐,動態(tài)類型有 Python璃吧、Ruby 等。

靜態(tài)類型和動態(tài)類型有什么區(qū)別呢废境?為什么在程序語言設(shè)計(jì)時要考慮是靜態(tài)還是動態(tài)畜挨?在寫代碼時筒繁,Python 寫起來簡潔,效率高巴元,可能100行 Java 的程序10行 Python 就能搞定毡咏,所以以前我覺得靜態(tài)類型的語言有點(diǎn)太死板了,不如動態(tài)類型的逮刨。但是經(jīng)過這段時間編程語言的學(xué)習(xí)呕缭,不能說一個比另一個好,個有所長吧修己。這篇文章從3個角度恢总、6個方面對比靜態(tài)類型和動態(tài)類型。

為什么會有靜態(tài)類型/動態(tài)類型的概念睬愤?

程序都需要進(jìn)行錯誤的檢查片仿。比如 3 / 0,這個程序會有錯誤戴涝,我們應(yīng)該在什么時候進(jìn)行檢查呢滋戳?

  1. 在寫程序時钻蔑,只要編輯器里出現(xiàn)除以0啥刻,報(bào)錯。
  2. 在編譯時咪笑,如果檢查到了除以0可帽,報(bào)錯。
  3. 在程序運(yùn)行時窗怒,運(yùn)行到了除以9映跟,報(bào)錯。
  4. 不報(bào)錯扬虚,返回?zé)o窮大 (+inf.0)努隙。

不同的語言設(shè)計(jì)上會選擇在這4個過程中不同時候去報(bào)錯。靜態(tài)類型和動態(tài)類型的區(qū)別在于什么時候報(bào)類型的錯誤辜昵?荸镊,比如說 3 / "a“,靜態(tài)類型多是在編譯時堪置,動態(tài)類型多是在程序運(yùn)行時躬存。怎么報(bào)類型的錯誤呢?語言里會有類型檢查的機(jī)制舀锨,類型檢查的目的是避免程序發(fā)生一些事情岭洲。

編程語言在設(shè)計(jì)時,要考慮 什么程序要類型檢查坎匿?盾剩,怎么執(zhí)行類型檢查雷激?。靜態(tài)類型和動態(tài)類型是這兩個問題不同回答的產(chǎn)物告私。

從寫代碼的角度對比

方便性 Convenience

靜態(tài)類型更好:靜態(tài)類型比較方便侥锦,因?yàn)椴挥萌z查 x 是不是 number,* 默認(rèn)只能是 number德挣。

; Racket
(define (cube x) 
  (if (not (number? x)) 
      (error "bad arguments")
      (* x x x)))

(* ML *)
fun cube x = x * x * x

動態(tài)類型更好:動態(tài)類型比較方便恭垦,因?yàn)橐粋€函數(shù)可以根據(jù)需要返回不同的類型。靜態(tài)類型卻需要去構(gòu)造一個新的數(shù)據(jù)類型才能實(shí)現(xiàn)格嗅。

; Racket
(define (f y) (if (> y 0) (+ y y) "hi"))
  
  
(* ML *)
datatype t = Int of int | String of string
fun f y = if y > 0 then Int(y+y) else String "hi"

fun foo x = case f x of
        Int i => Int.toString i
          | String s => s

更早的發(fā)現(xiàn)錯誤 Catching bugs earlier

靜態(tài)類型在編譯時就能發(fā)現(xiàn)類型上的錯誤番挺,都不用寫 tests,可以比動態(tài)類型更早的找到 bug屯掖。

但是喜歡動態(tài)類型的人會說玄柏,靜態(tài)類型只能找到"簡單"的錯誤,還是需要寫單元測試的贴铜,在寫單元測試時粪摘,肯定就能發(fā)現(xiàn)這些"簡單"的錯誤了。

性能 Performance

靜態(tài)類型的程序在運(yùn)行時更快绍坝,因?yàn)樵诰幾g時已經(jīng)進(jìn)行了檢測徘意,不需要去儲存和檢測類型,可以節(jié)省程序運(yùn)行的時間和空間轩褐。

但是喜歡動態(tài)類型的人會說椎咧,動態(tài)類型在性能很關(guān)鍵的部分,可以有一些辦法去優(yōu)化類型的儲存和檢測把介,比如說 (let ([x (+ y y)]) (* x 4))勤讽,有兩個 y,可以只檢測一個拗踢,4 是一個整數(shù)脚牍,不需要檢測,x 是 y + y 的結(jié)果巢墅,所以后面的那個 x 也可以不用檢測诸狭。通過這些方式可以對程序進(jìn)行一些優(yōu)化,而不需要像靜態(tài)類型一樣要受到各種類型的限制砂缩。

代碼重用 Code Reuse

動態(tài)類型更好:動態(tài)類型代碼重用率更高作谚,因?yàn)闆]有嚴(yán)格的類型系統(tǒng),代碼可以被不同類型的數(shù)據(jù)重用庵芭。一個最簡單的例子

# Ruby
def double x
    x + x
end

x 可以是數(shù)字妹懒,把數(shù)字翻倍。x 可以是 string双吆,把兩個 string 連在一起眨唬。

動態(tài)類型中一個 list 里可以有不同的類型的數(shù)據(jù)会前,在循環(huán)遍歷時會,能重用更多代碼匾竿。

靜態(tài)類型更好:靜態(tài)類型也有代碼重用的很多方法瓦宜,比如泛型,子類型等等岭妖。而且一個 list 只有一種類型的數(shù)據(jù)临庇,可以避免一些難找的bug,也可以避免因?yàn)轭愋妥杂啥鵀E用一些庫昵慌。

原型開發(fā) Prototyping

動態(tài)類型更好:動態(tài)類型更適合原型開發(fā)假夺,因?yàn)樵?Prototyping 時,不一定知道確切的數(shù)據(jù)結(jié)構(gòu)和函數(shù)斋攀,類型上的自由可以不用在做原型時就確定數(shù)據(jù)結(jié)構(gòu)已卷,導(dǎo)致了要一直不斷的去滿足類型的檢查,降低了原型開發(fā)的效率淳蔼。

靜態(tài)類型更好:雖然效率上不一定比的上動態(tài)類型侧蘸,靜態(tài)類型能更好的記錄整個系統(tǒng)在 Prototyping 的過程中,可以知道整個過程數(shù)據(jù)類型鹉梨、數(shù)據(jù)結(jié)構(gòu)是怎么變化的讳癌。如果是跟之前完全不相關(guān)的代碼,可以直接重寫俯画,不需要在之前的做更改析桥。在之前代碼不確定的地方,可以用一些表示所有其他類型的方法艰垂,比如 | _ => raise Unimplemented

再開發(fā)和維護(hù) Evolution & Maintaince

動態(tài)類型更好:在更改代碼時埋虹,可以把代碼能接受的變得更"寬"猜憎,比如說修改函數(shù)返回類型,調(diào)用的代碼如果對返回類型沒有問題搔课,可以不用更改胰柑。靜態(tài)類型必須要更改所有調(diào)用的代碼,不能進(jìn)行局部的測試爬泥。

靜態(tài)類型更好:動態(tài)類型的不用更改舊代碼是一個隱患柬讨,坊間流傳動態(tài)類型是「寫時一時爽,重構(gòu)火葬場」袍啡,靜態(tài)類型的類型檢查會列出所有需要更改的地方踩官,可以避免一些隱藏的bug。

總結(jié)

經(jīng)過這些對比境输,可以看出靜態(tài)類型和動態(tài)類型各有所長蔗牡,不能簡單粗暴的說一種比另外一種更好颖系。個人而言,我覺得動態(tài)類型更適合比較小的程序辩越,像 Python嘁扼,Ruby,做為腳本語言黔攒,能簡單快速的寫完對文件的處理等趁啸。動態(tài)類型 Java 和 C++ 則能過支持大型的軟件工程項(xiàng)目。

當(dāng)然具體選擇靜態(tài)類型或者動態(tài)類型督惰,取決于想要什么時候做類型檢查莲绰?想要什么樣的語言特性,并且應(yīng)該知道選擇的 trade-off 是什么樣的姑丑。

Reference

Coursera Programming Languages, Part B Week 3

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛤签,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子栅哀,更是在濱河造成了極大的恐慌震肮,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件留拾,死亡現(xiàn)場離奇詭異戳晌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)痴柔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門沦偎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人咳蔚,你說我怎么就攤上這事豪嚎。” “怎么了谈火?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵侈询,是天一觀的道長。 經(jīng)常有香客問我糯耍,道長扔字,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任温技,我火速辦了婚禮革为,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舵鳞。我一直安慰自己震檩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布系任。 她就那樣靜靜地躺著恳蹲,像睡著了一般虐块。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘉蕾,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天贺奠,我揣著相機(jī)與錄音,去河邊找鬼错忱。 笑死儡率,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的以清。 我是一名探鬼主播儿普,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼掷倔!你這毒婦竟也來了眉孩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤勒葱,失蹤者是張志新(化名)和其女友劉穎浪汪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凛虽,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡死遭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凯旋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呀潭。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖至非,靈堂內(nèi)的尸體忽然破棺而出钠署,到底是詐尸還是另有隱情,我是刑警寧澤睡蟋,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布踏幻,位于F島的核電站,受9級特大地震影響戳杀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夭苗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一信卡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧题造,春花似錦傍菇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牵触。三九已至,卻和暖如春咐低,著一層夾襖步出監(jiān)牢的瞬間揽思,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工见擦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钉汗,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓鲤屡,卻偏偏與公主長得像损痰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子酒来,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345