<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    冒號(hào)課堂§5.2:數(shù)據(jù)類型

     

    冒號(hào)課堂

    第五課 語(yǔ)言小談(2)

    5.2數(shù)據(jù)類型——規(guī)則與變通

    操縱于規(guī)矩之中,神明于規(guī)矩之外                        ——《俞震·古今醫(yī)案按》

     

    關(guān)鍵詞:      數(shù)據(jù)類型,靜態(tài)類型,動(dòng)態(tài)類型,Duck類型,強(qiáng)類型,弱類型,類型安全

    摘要:   關(guān)于數(shù)據(jù)類型的討論

     

    預(yù)覽

    ·           Duck類型的哲學(xué)是:名義不重要,重要的是能力

    ·           將一個(gè)會(huì)叫會(huì)游的家伙放進(jìn)池塘看起來(lái)不算壞主意,但如果一艘輪船趁機(jī)也轟隆隆地開了進(jìn)來(lái),事情恐怕就不那么美妙了

    ·           靜態(tài)類型檢查類似“疑罪從有”的有罪推定制,動(dòng)態(tài)類型檢查類似“疑罪從無(wú)”的無(wú)罪推定制

    ·           盡可能守規(guī)則,必要時(shí)求變通

    ·           規(guī)則如褲帶,過(guò)于寬松和過(guò)于束縛都不好

     

     提問

    ·           動(dòng)態(tài)語(yǔ)言與動(dòng)態(tài)類型語(yǔ)言是一回事嗎?

    ·           數(shù)據(jù)類型有哪兩個(gè)要素?其意義何在?

    ·           什么是動(dòng)態(tài)類型和靜態(tài)類型?它們的區(qū)別是什么?各有什么優(yōu)缺點(diǎn)?

    ·           什么是鴨子類型(duck typing)?它有什么優(yōu)缺點(diǎn)?

    ·           什么是強(qiáng)類型與弱類型?什么是類型安全的?


    講解

    待教室平靜下來(lái),冒號(hào)再度開腔:“在談?wù)搫?dòng)態(tài)語(yǔ)言之前,最好先澄清一下它與動(dòng)態(tài)類型語(yǔ)言之間的區(qū)別。”

    嘆號(hào)訝然道:“它們不是一回事嗎?一直以為動(dòng)態(tài)語(yǔ)言是動(dòng)態(tài)類型語(yǔ)言的簡(jiǎn)稱呢。”

    “有親戚之名,卻無(wú)血緣之親。名稱上相似,加之動(dòng)態(tài)語(yǔ)言絕大多數(shù)確是動(dòng)態(tài)類型語(yǔ)言,造成混淆實(shí)屬在所難免,但二者之間并無(wú)必然聯(lián)系——?jiǎng)討B(tài)語(yǔ)言不一定是動(dòng)態(tài)類型語(yǔ)言[1],動(dòng)態(tài)類型語(yǔ)言也不一定是動(dòng)態(tài)語(yǔ)言[2]。”冒號(hào)飛跑的舌頭幾乎絆蒜,同時(shí)把眾人的腦子攪成了一鍋粥。

    見勢(shì)不妙,冒號(hào)改用迂回戰(zhàn)術(shù):“我們不妨再談開些,大家對(duì)數(shù)據(jù)類型是如何理解的?”

    逗號(hào)隨口道:“數(shù)據(jù)類型不就是數(shù)據(jù)的種類嗎?”

    眾人暗笑:說(shuō)了跟沒說(shuō)差不多。

    冒號(hào)說(shuō)道:“數(shù)據(jù)類型包含兩個(gè)要素:一個(gè)是允許取值的集合,一個(gè)是允許參與的運(yùn)算。例如int類型在Java中既定義了介于− 231 231 − 1之間的整數(shù)集合,也定義了該集合上的整數(shù)所能進(jìn)行的運(yùn)算。現(xiàn)在的問題是:數(shù)據(jù)類型的意義何在?”

    句號(hào)回答:“限定一個(gè)變量的數(shù)據(jù)類型,就意味著限制了該變量的取值范圍和所參與的運(yùn)算,這從一定程度上保證了代碼的安全性。”

    冒號(hào)追問:“還有嗎?”

    句號(hào)略作思考后說(shuō):“用戶自定義的數(shù)據(jù)類型,如C中的結(jié)構(gòu)和Java中的類或接口,賦予數(shù)據(jù)以邏輯內(nèi)涵,提高了代碼的抽象性。”

    “精辟!”冒號(hào)贊道,“數(shù)據(jù)類型既有針對(duì)機(jī)器的物理意義,又有針對(duì)人的邏輯意義。前者用于進(jìn)行底層的內(nèi)存分配和數(shù)值運(yùn)算等,后者用于表達(dá)高層的邏輯概念。既然類型如此重要,類型檢查就必不可少了[3]。所謂動(dòng)態(tài)類型語(yǔ)言dynamic typing language),正是指類型檢查發(fā)生在運(yùn)行期間run-time)的語(yǔ)言。”

    “那靜態(tài)類型語(yǔ)言static typing language)自然是類型檢查發(fā)生在編譯期間compile-time)的語(yǔ)言咯。”引號(hào)接話道。

    冒號(hào)回應(yīng):“一般的說(shuō)法是這樣,但我更愿意將‘編譯期間’四個(gè)字改為‘運(yùn)行之前’,否則容易讓人誤解為靜態(tài)類型語(yǔ)言一定是編譯型語(yǔ)言(compiled language)。”

    問號(hào)問道:“是否可以這么說(shuō):靜態(tài)類型語(yǔ)言需要變量聲明,而動(dòng)態(tài)類型語(yǔ)言則不需要?”

    “這話只對(duì)了一半。”冒號(hào)評(píng)論,“動(dòng)態(tài)類型語(yǔ)言固然不需要顯式的變量聲明(explicit declaration,一些靜態(tài)類型語(yǔ)言有時(shí)也不需要。典型的如ML、Haskell之類的函數(shù)式語(yǔ)言,編譯器可以通過(guò)上下文來(lái)進(jìn)行類型推斷(type inference)。”

    “如何進(jìn)行類型推斷?”問號(hào)有點(diǎn)丈二和尚摸不著頭腦。

    冒號(hào)打了個(gè)比方:“假設(shè)‘+’號(hào)只限于同類型的數(shù)據(jù)運(yùn)算,那么從表達(dá)式a + 1中可以推出a是整型變量,從b + 1.0中推出b是浮點(diǎn)型變量,從c + “1”中推出c是字符串型變量。這些變量不必事先聲明,但一旦類型被推斷確定后,便不再更改。由于這些推斷都是在程序運(yùn)行之前進(jìn)行的,因此仍屬于靜態(tài)類型。它既有動(dòng)態(tài)類型的簡(jiǎn)潔性,又不失聲明式靜態(tài)類型的安全性,可謂裁長(zhǎng)補(bǔ)短啊。”

    嘆號(hào)有些羨慕地說(shuō):“還是動(dòng)態(tài)類型語(yǔ)言好,不僅不必聲明變量,而且一個(gè)變量在不同地方還可以代表不同類型,多省事多方便啊!”

    冒號(hào)微微頷首:“雖然這種機(jī)制也有為人詬病之處,但不可否認(rèn),動(dòng)態(tài)類型語(yǔ)言的確有它的優(yōu)勢(shì):簡(jiǎn)明、快捷、靈活,并且天然具有泛型(generic)特征。值得一提的是,動(dòng)態(tài)類型有一種被稱作鴨子類型(duck typing)的形式。”

    逗號(hào)感到有趣:“鴨子類型?很滑稽的名字。”

    “這種類型通俗的說(shuō)法是:如果一個(gè)對(duì)象既會(huì)走鴨步又會(huì)呷呷叫,何妨將其視作鴨子呢?”冒號(hào)說(shuō)著投影出一段Ruby代碼——

    class Duck                        #會(huì)叫會(huì)游的鴨

        def shout

            puts '呷呷呷'

        end

        def swim

            puts '鴨泳'

        end

    end

    class Frog                         #會(huì)叫會(huì)游的蛙

        def shout

            puts '呱呱呱'

        end

        def swim

           puts '蛙泳'

        end

    end

    def shoutAndSwim(duck)   #讓一只會(huì)叫會(huì)游的家伙邊叫邊游

        duck.shout

        duck.swim

    end

    shoutAndSwim(Duck.new)   #讓一只鴨邊叫邊游

    shoutAndSwim(Frog.new)   #讓一只蛙邊叫邊游

    冒號(hào)繼續(xù)講解:“在Smalltalk、Python和Ruby等動(dòng)態(tài)類型的OOP語(yǔ)言中,只要一個(gè)類型具有shout和swim的方法,它就可以為shoutAndSwim所接受。這在C++、Java、C#等靜態(tài)類型語(yǔ)言中是不可能的[4],除非鴨和蛙在同一繼承樹上,或者二者均顯式實(shí)現(xiàn)了一個(gè)包含shout和swim的公用接口。”

    句號(hào)敏銳地指出:“C++是靜態(tài)類型語(yǔ)言,但它的模板也可實(shí)現(xiàn)類似功能,并不需要引入繼承關(guān)系。”

    “說(shuō)得很對(duì)!但請(qǐng)接著看下去。”冒號(hào)又放出一段投影——

    class Cock                                 #會(huì)叫不會(huì)游的雞

        def shout

            puts '喔喔喔'

        end

    end

    class Fish                               #會(huì)游不會(huì)叫的魚

        def swim

            puts '自由泳'

        end

    end

    def shoutOrSwim(duck, flag)   #讓一只會(huì)叫或會(huì)游的家伙叫或游

        flag ? duck.shout : duck.swim

    end

    shoutOrSwim(Cock.new, true)       #讓一只雞叫

    shoutOrSwim(Fish.new, false)       #讓一只魚游

    “這里雞沒有swim的方法,魚沒有shout的方法。若采用C++的模板,shoutOrSwim是無(wú)法通過(guò)編譯的。但在支持Duck 類型的語(yǔ)言中,只要在運(yùn)行期間不讓雞swim、讓魚shout——除非你突發(fā)奇想——一切平安無(wú)事。”冒號(hào)作了個(gè)OK的手勢(shì)。

    “動(dòng)態(tài)類型語(yǔ)言真是越看越可愛。”嘆號(hào)簡(jiǎn)直垂涎欲滴了。

    “Duck類型的哲學(xué)是:名義不重要,重要的是能力,頗有些實(shí)用主義的味道。這種非繼承性多態(tài)為軟件重用開啟了新的窗口,同時(shí)也埋下了一些陷阱。由于Duck類型的接口組合是隱性的,其使用者需要比普通interface更小心以避免誤用;其維護(hù)者也需要更小心以避免破壞客戶代碼;另外它也可能造成濫用——將一個(gè)會(huì)叫會(huì)游的家伙放進(jìn)池塘看起來(lái)不算壞主意,但如果一艘輪船趁機(jī)也轟隆隆地開了進(jìn)來(lái),事情恐怕就不那么美妙了。”

    眾皆莞爾。

    “再來(lái)看看靜態(tài)類型語(yǔ)言的好處:由于在運(yùn)行之前進(jìn)行了類型檢查,一方面代碼的可靠性增強(qiáng),符合發(fā)現(xiàn)錯(cuò)誤要盡早的原則;另一方面編譯器有可能藉此優(yōu)化機(jī)器代碼以提高運(yùn)行效率,同時(shí)相比前者節(jié)省了運(yùn)行期的耗費(fèi)在類型檢查上的時(shí)間和空間。此外,變量類型的聲明彰顯了編程者的意圖,有輔助文檔的功效。”冒號(hào)有條有理地解釋著,“兩種類型的體制可以用兩種法律原則來(lái)類比:靜態(tài)類型檢查類似‘疑罪從有’的有罪推定制——在被證明合法之前是非法的,動(dòng)態(tài)類型檢查類似‘疑罪從無(wú)’的無(wú)罪推定制——在被證明非法之前是合法的。至于如何取舍,套用一句話:‘Static Typing Where Possible, Dynamic Typing When Needed’。不妨理解為:盡可能守規(guī)則,必要時(shí)求變通。”

    句號(hào)俏皮地說(shuō):“規(guī)則如褲帶,過(guò)于寬松和過(guò)于束縛都不好。”

    問號(hào)提出新問題:“動(dòng)態(tài)類型語(yǔ)言與弱類型語(yǔ)言有何不同?”

    冒號(hào)喟言:“它們也常常被混為一談,但類型的動(dòng)靜與強(qiáng)弱完全是正交的兩個(gè)概念。靜態(tài)類型語(yǔ)言中,有強(qiáng)類型的Java,也有弱類型的C;動(dòng)態(tài)類型語(yǔ)言中,有強(qiáng)類型的Smalltalk,也有弱類型的JavaScript。前者以類型的綁定(binding)時(shí)間來(lái)劃分,后者以類型的約束強(qiáng)度來(lái)劃分。通常弱類型語(yǔ)言weakly-typing language)允許一種類型的值隱性轉(zhuǎn)化為另一種類型[5]。舉個(gè)例子,1"2"VB中等于3——第二個(gè)字符串轉(zhuǎn)化為整數(shù);在JavaScript中等于"12"——第一個(gè)整數(shù)轉(zhuǎn)化為字符串;在C中則等于一個(gè)不定的整數(shù)值——第二個(gè)字符串作為地址來(lái)運(yùn)算。這樣似乎很有趣很方便,但程序容易藏污納垢,滋生臭蟲(bug)。與此相對(duì)地,強(qiáng)類型語(yǔ)言strongly-typed language)著意貫徹類型控制,為保障數(shù)據(jù)的完整性和代碼的安全有效性,一般不允許隱性類型轉(zhuǎn)換[6]。如果一定需要類型轉(zhuǎn)換,必須是顯性轉(zhuǎn)換,一般通過(guò)我們熟知的鑄型cast)來(lái)完成。”

    引號(hào)想起:“好像還有一種所謂的類型安全語(yǔ)言?”

    逗號(hào)緊緊抱著頭,仿佛害怕裂開。

    “類型按安全性來(lái)劃分,可分為類型安全語(yǔ)言(type-safe language)和類型不安全語(yǔ)言(type-unsafe language)。類型檢查的目的就是為了避免類型錯(cuò)誤(type error[7],即杜絕因類型問題而產(chǎn)生的錯(cuò)誤或不良代碼。如果一個(gè)類型系統(tǒng)能完全做到這一點(diǎn),它就被稱為類型安全的。雖然尚存爭(zhēng)議,但一般認(rèn)為強(qiáng)類型語(yǔ)言對(duì)類型控制更嚴(yán)格,因而是類型安全的,弱類型語(yǔ)言是類型不安全的。類型安全固然對(duì)保障程序的合理性和可靠性十分重要,但若過(guò)于嚴(yán)苛,程序也就失去了活力,正所謂‘水至清則無(wú)魚’啊。” 冒號(hào)有條不紊地解說(shuō)著,“至此,我們已論及數(shù)據(jù)類型的三種劃分方式。需要說(shuō)明的是,這些劃分并非涇渭分明的[8],更多的是定性而非定量的描述,甚至沒有公認(rèn)統(tǒng)一的定義。但了解它們,對(duì)我們理解編程語(yǔ)言和編程原則是大有裨益的。


    插語(yǔ)

    [1] Scala是動(dòng)態(tài)語(yǔ)言,卻是靜態(tài)類型的。

    [2] Visual Basic(不包括VB.NET) 支持動(dòng)態(tài)類型,卻是靜態(tài)語(yǔ)言。

    [3] 極少數(shù)語(yǔ)言沒有類型檢查(untypedtypeless),如大多數(shù)匯編語(yǔ)言、Forth語(yǔ)言等。

    [4] C#4.0將支持duck typing

    [5] 隱式轉(zhuǎn)換也稱為強(qiáng)制轉(zhuǎn)換(coercion)。有人將顯式轉(zhuǎn)換的鑄型(cast)譯為強(qiáng)制轉(zhuǎn)換,并不準(zhǔn)確。

    [6] 但許多強(qiáng)類型語(yǔ)言對(duì)于寬轉(zhuǎn)換(widening conversion)還是允許隱性的,如必要時(shí)int可自動(dòng)轉(zhuǎn)換為float

    [7] 典型的類型錯(cuò)誤是:一個(gè)函數(shù)本來(lái)期待的參數(shù)類型是A,實(shí)際傳入的變量a卻不是A類型。

    [8] 比如,靜態(tài)類型的OOP語(yǔ)言如C++Java支持downcasting,能在運(yùn)行期間進(jìn)一步細(xì)化數(shù)據(jù)類型,從某種意義上也具有動(dòng)態(tài)類型的特征。

     

    總結(jié)
    • 盡管動(dòng)態(tài)語(yǔ)言大多數(shù)是動(dòng)態(tài)類型語(yǔ)言,但二者并不是一回事。
    • 數(shù)據(jù)類型包含兩個(gè)要素:允許取值的集合和允許參與的運(yùn)算。
    • 數(shù)據(jù)類型既有針對(duì)機(jī)器的物理意義,又有針對(duì)人的邏輯意義,提高了代碼的安全性和抽象性。
    • 動(dòng)態(tài)類型的類型檢查發(fā)生在運(yùn)行期間,靜態(tài)類型的類型檢查發(fā)生在編譯期間(運(yùn)行之前)。
    • 動(dòng)態(tài)類型的變量不需要顯式聲明,靜態(tài)類型的變量需要通過(guò)顯式聲明或類型推斷。
    • 鴨子類型是動(dòng)態(tài)類型的一種風(fēng)格,允許非繼承性多態(tài),即一個(gè)對(duì)象的類型可以由其接口集合來(lái)確定,不需要通過(guò)顯式繼承。它有利于代碼重用,但也可能造成誤用和濫用。
    • 動(dòng)態(tài)類型語(yǔ)言的優(yōu)點(diǎn):代碼簡(jiǎn)明靈活、易于重用,適合泛型編程和快速原型開發(fā)。
    • 靜態(tài)類型語(yǔ)言的優(yōu)點(diǎn):運(yùn)行之前的類型檢查增強(qiáng)了代碼的可靠性,使編譯器有可能進(jìn)行優(yōu)化處理從而提高運(yùn)行效率,節(jié)省了運(yùn)行期的類型檢查所占用的時(shí)間和空間,同時(shí)類型聲明有輔助文檔的功效。
    • 靜態(tài)類型檢查實(shí)行“疑罪從有”的有罪推定制,動(dòng)態(tài)類型檢查實(shí)行“疑罪從無(wú)”的無(wú)罪推定制。取舍的原則是:Static Typing Where Possible, Dynamic Typing When Needed。即盡可能守規(guī)則,必要時(shí)求變通。
    • 類型的動(dòng)靜以類型的綁定時(shí)間來(lái)劃分,類型的強(qiáng)弱以類型的約束強(qiáng)度來(lái)劃分,它們之間沒有必然聯(lián)系。弱類型語(yǔ)言允許類型的隱性轉(zhuǎn)化,被認(rèn)為是類型不安全的;而強(qiáng)類型語(yǔ)言則一般不允許這種轉(zhuǎn)化,被認(rèn)為是類型安全的。

     

    “”參考

    [1] WikipediaType systemhttp://en.wikipedia.org/wiki/Type_system

    [2] Erik MeijerPeter DraytonStatic Typing Where Possible, Dynamic Typing When Neededhttp://research.microsoft.com/~emeijer/Papers/RDL04Meijer.pdf

    [3] Ravi SethiProgramming Languages: Concepts & Constructs(英文版第2).北京:機(jī)械工業(yè)出版社,2002136-143

     

    posted on 2009-01-08 00:02 鄭暉 閱讀(3161) 評(píng)論(0)  編輯  收藏 所屬分類: 冒號(hào)課堂

    導(dǎo)航

    統(tǒng)計(jì)

    公告

    博客搬家:http://blog.zhenghui.org
    《冒號(hào)課堂》一書于2009年10月上市,詳情請(qǐng)見
    冒號(hào)課堂

    留言簿(17)

    隨筆分類(61)

    隨筆檔案(61)

    文章分類(1)

    文章檔案(1)

    最新隨筆

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 99免费视频观看| 91精品视频在线免费观看| 亚洲国产精品高清久久久| 色老头永久免费网站| 精品国产呦系列在线观看免费| 67pao强力打造67194在线午夜亚洲 | 亚洲国产福利精品一区二区| 免费人成网站7777视频| www.黄色免费网站| a级毛片免费全部播放无码| 日韩精品亚洲专区在线影视| 亚洲国产精品yw在线观看| 久久精品亚洲一区二区| 免费国产真实迷j在线观看| 国产精品69白浆在线观看免费| 99久久婷婷免费国产综合精品| 人成免费在线视频| 免费夜色污私人影院网站电影 | 亚洲免费在线视频观看| 日韩精品在线免费观看| 久久香蕉国产线看免费| 日本免费高清视频| 国内精品免费麻豆网站91麻豆| 叮咚影视在线观看免费完整版| 久久久WWW成人免费精品| 四虎影视久久久免费观看| 日韩大片免费观看视频播放 | 久久综合久久综合亚洲| 午夜亚洲WWW湿好爽 | 99热免费在线观看| 爱爱帝国亚洲一区二区三区| 亚洲国产天堂在线观看| 亚洲精品无码专区久久久| 免费大片黄手机在线观看| 可以免费看的卡一卡二| 黄网站色在线视频免费观看| 欧美日韩亚洲精品| 国产va免费精品| 国产免费AV片在线播放唯爱网| 波多野结衣久久高清免费| 亚洲国产精品一区二区第一页|