自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

對象已死?

開發(fā) 后端 開發(fā)工具
最近出現(xiàn)了面向?qū)ο蠹夹g(shù)會滅亡的說法,并說函數(shù)式語言會取代面向?qū)ο蠹夹g(shù)成為主流方式。這一說法,是否屬實,讓我們來看本文作者的看法,對象真的已死??

最近常有一種說法,就是我們?nèi)缃衩媾R著另外一場編程模型的變革,面向?qū)ο蠹夹g(shù)已經(jīng)處在被淘汰的邊緣,函數(shù)式語言會取代面向?qū)ο蠹夹g(shù)成為主流方式,甚至出現(xiàn)了面向?qū)ο笠阉赖难哉摗W鳛橐粋€硬核函數(shù)語言的狂熱者,我個人當(dāng)然希望函數(shù)式語言可以一統(tǒng)天下,成為主流之選。但是不是應(yīng)該把對象技術(shù)和函數(shù)技術(shù)對立起來,說式后者取前者而代之,我個人認(rèn)為,這和如何看待面向?qū)ο蠹夹g(shù)有關(guān)。

做為工程實踐的對象技術(shù)

在這個年代,大家有一種神圣化面向?qū)ο蠹夹g(shù)的傾向,很多人都把對象技術(shù)奉為高深的思想和理論。但實際上,面向?qū)ο蠹夹g(shù)僅僅一種工程實踐而已,它是依托于其他技術(shù)而存在的一種實踐,本身并不是一種完備的計算模型。

在計算機科學(xué)發(fā)展的早期,對于計算機的非數(shù)值計算應(yīng)用的討論,以及對于可計算性問題的研究和發(fā)展,大抵確立了幾種的計算模型:遞歸函數(shù)類、圖靈機、Lambda演算、Horn子句、Post系統(tǒng)等等。其中遞歸函數(shù)類是可計算性問題的數(shù)學(xué)解釋;Horn子句是prolog這類邏輯語言的理論基礎(chǔ);lambda演算成為了函數(shù)式語言的理論基礎(chǔ);圖靈機是圖靈解決可計算問題的時候所設(shè)計的裝置,其后成為計算機的裝置模型,與圖靈機相關(guān)的自動機以及馮諾依曼結(jié)構(gòu),成為了命令式語言的理論基礎(chǔ)。

因此當(dāng)我們談及函數(shù)語言和命令式語言優(yōu)劣的時候,我們實際上是在討論其背后的計算模型——也就是lambda演算和馮結(jié)構(gòu)裝置操作——在執(zhí)行效率和抽象層次上的優(yōu)劣。

而面向?qū)ο蠹夹g(shù)則比較尷尬了,其背后沒有一個對應(yīng)的計算模型(80年代的時候曾有人研究過,Pi演算是個備選,但是這個模型更多的是在并發(fā)對象領(lǐng)域的語義,而不是通常意義上的計算模型)。它有點類似于“***實踐”,在不同的計算模型上有著完全不同實現(xiàn)方式和含義。因此對比對象技術(shù)和其他技術(shù)的時候,搞清楚到底是哪一種面向?qū)ο缶妥兊酶裢庵匾饋怼?/p>

兩種不同的面向?qū)ο?/strong>

目前流行的對象技術(shù),實際上有兩個截然不同的源頭。它們分別在兩個完全不同的計算模型上發(fā)展起來,但是都頂著“面向?qū)ο?rdquo;這個帽子。

***種對象技術(shù)出現(xiàn)的較晚,在1979年以后。它是以抽象數(shù)據(jù)類型(ADT,Abstract Data Type)為源起,發(fā)展出來的面向?qū)ο蠹夹g(shù)。也就是首先被C++所采用的面向?qū)ο蠹夹g(shù)。

C++作為“更好的C”,繼承了C語言對于程序的看法,也就是數(shù)據(jù)抽象(Data Abstraction)和過程。面向?qū)ο蠹夹g(shù)在C++中,是作為一種更好的數(shù)據(jù)抽象的方式而存在的。

數(shù)據(jù)抽象在這類面向?qū)ο笳Z言中是一種關(guān)鍵的抽象方式。所謂數(shù)據(jù)抽象,在計算機發(fā)展的早期是一種非常關(guān)鍵的技術(shù)。眾所周知,計算機在裝置模型上是一個存儲和一組指令集,而二進(jìn)制的存儲實際上是沒有任何類型表示的。整數(shù),浮點這些操作必須通過相應(yīng)的約定,再以指令集的形式進(jìn)行支持。而隨著計算機的發(fā)展,簡單的數(shù)據(jù)類型顯然已經(jīng)不能滿足應(yīng)用的需要。這時候一種靈活且有效的類型系統(tǒng),就成了一種自然的追求(直到80年代初,類型系統(tǒng)都是計算機科學(xué)研究的重要方向之一)。

在C++中(以及后來的Java和C#),對象是一種構(gòu)造數(shù)據(jù)類型的方式,把每個“類”看作一段存儲(狀態(tài))和操作(方法)的集合。“類”作為已經(jīng)存在的類型系統(tǒng)的一種擴展(這一點在C++中體現(xiàn)得尤其強烈)。在這類語言種,“類”(class)實際上代替了“對象”(object)成為了頭等公民。構(gòu)造一個更好的類型系統(tǒng),是這種面向?qū)ο蠹夹g(shù)所要解決的問題。與其說是面向?qū)ο?,不如說是面向類或面向類型的。

從計算語義上說,這類對象技術(shù)仍然是裝置的操作語義,和面向過程的沒有實質(zhì)上的區(qū)別。唯一的不同是,被這種對象語言操作的機器,可以借由對象技術(shù)擴展機器所支持的類型。這種面向?qū)ο蠹夹g(shù)是過程技術(shù)的一種發(fā)展,雖然在抽象層次上沒有什么太大的提高,但在實踐上已經(jīng)是巨大的進(jìn)步。

另一種對象技術(shù)出現(xiàn)的很早,大概在60年代末就出現(xiàn)了,直到80年代初還有發(fā)展。但是很長一段時間內(nèi)并不是太主流的做法,反而并不太為人所知。

在函數(shù)式語言里,因為高階函數(shù)(High Order Function)的存在,數(shù)據(jù)可由函數(shù)來表達(dá)。這就是函數(shù)語言里一個非常重要的觀點:Data as Procedure。在函數(shù)語言中,可以構(gòu)造一種非常類似于對象的高階函數(shù):

  1. (define (make-user name age sex)  
  2. (define (dispatch message)  
  3. (cond ((eq? message 'getName) name)  
  4. ((eq? message 'getAge) age)  
  5. ((eq? message 'getSex) sex))  
  6. (else (error 'messageNotUnderstand))))dispatch)  
  7. (define vincent (make-user 'Vincent 30 'Male))  
  8. (vincent 'getName) 

如上面的Lisp代碼所示,可以借由返回一個dispatch函數(shù),將基本數(shù)據(jù)組合成一個更復(fù)雜的數(shù)據(jù)對象,而通過高階函數(shù)的后續(xù)調(diào)用,可以使用相應(yīng)的選擇器(selector)與數(shù)據(jù)對象交互。這種風(fēng)格的數(shù)據(jù)抽象被稱作“消息傳遞”(Message Passing),是早期面向?qū)ο蠹夹g(shù)的雛形,無論是Smalltalk還是CLOS都是以這種技術(shù)為藍(lán)本,設(shè)計的對象系統(tǒng),包括后來的Ruby,實際上也是這種模型的一個發(fā)展。

因此實際上,就算在函數(shù)式語言上面,我們?nèi)匀豢梢酝ㄟ^引入這種對象的形式,對函數(shù)進(jìn)行相應(yīng)的模塊化和局部化。這種形式的對象與函數(shù)本身沒有任何差別,因此這種類型的對象系統(tǒng),被稱作“方便的接口”,用于簡化對象的函數(shù)的訪問和調(diào)用。

在函數(shù)式語言里,另一個非常重要的概念就是“副作用”(Side effect,即函數(shù)可以修改某個存在的狀態(tài))。像Lisp并不是純函數(shù)語言,因此是允許狀態(tài)修改的。因此對象技術(shù)除了可以被看作函數(shù)局部化和模塊化的方法之外,還可以看作副作用局部化的一種方式。采用這類面向?qū)ο蠹夹g(shù)的語言,通常被稱作動態(tài)面向?qū)ο笳Z言。

這類對象語言通常都會保持一些函數(shù)式語言的特性,比如lambda的各種變體,比如較容易的函數(shù)組合,比如curry,比如高階函數(shù)。而且由于這類對象系統(tǒng)是從函數(shù)式發(fā)展出來的,也更加推崇一些副作用小的,利用高階函數(shù)的對象設(shè)計方法。比如,不變體(Immutable object)回調(diào)等等。

計算語義上,無副作用的對象系統(tǒng)實際上和Lambda演算享有同樣的計算語義。而帶副作用的本身只能被看作一種壞的實現(xiàn),在函數(shù)上都沒有明確語義。僅僅能夠看作對于副作用的局部化和模塊化。

以上,我們簡單地看了一下兩種不同的“面向?qū)ο?rdquo;技術(shù)。其中一種是用來解決如何構(gòu)造更好的類型系統(tǒng)的,另一種是用來對函數(shù)和副作用進(jìn)行有效模塊化和局部化的。如果單以這兩種面向?qū)ο蠹夹g(shù)和函數(shù)式語言去比較,實在不是一個層次的東西。那么為什么我們最近能夠聽到這么多函數(shù)和對象的討論呢?

新的發(fā)展

靜態(tài)類型函數(shù)語言

最早的函數(shù)語言是不太在意類型的,因為有Data as Procedure的存在,lambda演算可以通過把參數(shù)類型抽象成另一個高階函數(shù)來繞過函數(shù)參數(shù)類型問題(把參數(shù)也變成lambda,每個函數(shù)都看作參數(shù)和函數(shù)體的高階)。然而隨著形式化類型系統(tǒng)在理論上的發(fā)展,把lambda演算擴展為typed lambda演算自然就是一種很自然的推論。

隨著在此基礎(chǔ)上發(fā)展出來的ML族和Haskell語言的日漸成熟,以及代數(shù)數(shù)據(jù)類型(algebraic data type)的引入,這些語言可以較為容易地構(gòu)造出非常復(fù)雜的類型系統(tǒng)。而且伴隨著類型推演和類型計算的引入,類型間復(fù)雜的關(guān)系也可以較為容易表達(dá)。由此,靜態(tài)類型函數(shù)式語言也開始挑戰(zhàn)以對象為基礎(chǔ)的類型系統(tǒng)構(gòu)造方法。

實際上這里函數(shù)語言的挑戰(zhàn)是類型系統(tǒng)之爭,而非面向?qū)ο蠛秃瘮?shù)語言之爭。因此,消息傳遞類的對象語言根本不在討論之列,而對于靜態(tài)類型面向?qū)ο笳Z言而言,除了C++外(而對于C++,面向?qū)ο髢H僅是構(gòu)造類型系統(tǒng)的一種方式,另一種則是著名的范型編程。我仍然相信,在語義上靜態(tài)類型函數(shù)語言會勝過C++很多,但是彈性和表現(xiàn)力C++并不會差太多),其他主流語言如Java和C#,類型系統(tǒng)的已經(jīng)被限制在一個相對簡單的范疇內(nèi),說完敗也不為過。

主流平臺也為需要處理復(fù)雜類型系統(tǒng)的開發(fā)者提供了不同的選擇,比如.NET平臺上的F#。以及JVM上的Scala。都是在主流平臺上引入靜態(tài)類型函數(shù)語言的一些特征,來簡化復(fù)雜類型系統(tǒng)的構(gòu)造。

并發(fā)編程/并行計算/多核編程

Lisp并不是一個純函數(shù)語言,它允許有副作用存在。后來發(fā)展了一些嚴(yán)格的純函數(shù)語言,嚴(yán)格禁止副作用。也就是所有變量都和數(shù)學(xué)中的變量具有相同的語義,不能修改。然而計算機程序終歸是要處理狀態(tài)變化、輸入輸出這些不具有函數(shù)語義的操作的。一些純函數(shù)語言開始引入了更精巧的方式來管理狀態(tài),比如Monad。Monad的傳遞性使得副作用的擴散在函數(shù)中變得更明確可見。

這種方式本來是用來解決純函數(shù)語言內(nèi)副作用處理的一種技巧,但是恰好趕上Intel受制于生產(chǎn)技術(shù),無法再通過提高單核頻率以追趕摩爾定律,必須通過集成多核的方式來制造更快的CPU。多核CPU作為一種新的事物,給計算機界帶來了新的恐慌,大家覺得有必要使用一種新的編程模型以充分利用多核的優(yōu)勢。

而***個嘗試的方案就是將計算分布到多個CPU上,也就是利用多核進(jìn)行并行計算。這時候,純函數(shù)式語言對于副作用的處理,恰好給多核編譯器提供了一個理想的優(yōu)化方式:即所有無作用的函數(shù)皆可以隨意分布到多核上,而帶副作用的函數(shù)則無法分布。通過對于類型系統(tǒng)的簡單識別和標(biāo)注,就可以自動地將純函數(shù)式程序編譯為支持多核的程序。這在一段時間內(nèi),形成一種函數(shù)式語言是自動適應(yīng)多核的,而面向?qū)ο蟪绦騽t需要重寫的印象。一時間內(nèi),函數(shù)與對象之間的選擇實際上變成了多核和單核的選擇。

好在還有Amdahl's law存在,事實也證明除去一些特定的應(yīng)用場景,自動編譯為支持多核并行的函數(shù)式程序并不快多少,而轉(zhuǎn)化為純函數(shù)程序的成本卻高出不少,同時大多數(shù)純函數(shù)語言都帶有學(xué)術(shù)性質(zhì),對于團隊開發(fā)并不友好。在加上JVM和.NET CLR對于多核都做出了一些回應(yīng)。因此除去一些計算密集型應(yīng)用,純函數(shù)語言并沒比面向?qū)ο蠛枚嗌佟?/p>

峰回路轉(zhuǎn)的是,由消息傳遞風(fēng)格發(fā)展出來的actor模型,利用操作系統(tǒng)的進(jìn)程/線程特性,在一個合理的粒度上很好地利用了多核的能力,簡化了并發(fā)編程。雖然***個著名的實現(xiàn)是Erlang的actor系統(tǒng),但是由于消息傳遞風(fēng)格和面向?qū)ο竽P拖嗳ゲ贿h(yuǎn),很快就在各種面向?qū)ο笳Z言中有了類庫支持。雖然利用當(dāng)代函數(shù)語言的語法特性,actor可以實現(xiàn)得更簡潔,但是對象對于副作用和狀態(tài)的封裝,更好地解決了在并發(fā)環(huán)境下對于共享狀態(tài)的操作,反而有了更好的發(fā)展。

以上,我們看了函數(shù)式語言中兩個新的發(fā)展,以及圍繞這些發(fā)展涉及的一些“對象v.s.函數(shù)”的討論。正如本文一開始所說,對象技術(shù)作為一種工程實踐,其發(fā)展總是依托于其他更基本的計算模型的演化的。函數(shù)語言的發(fā)展,使得我們對于對象的認(rèn)識和理解有了更深更好的認(rèn)識。而對象作為函數(shù)的“方便的接口”總會在新的發(fā)展中,讓我們更加便利的享有函數(shù)式和其他計算模型發(fā)展的成果。

回到本文最開始的討論,函數(shù)的發(fā)展會的確會促使一些對象技術(shù)的消亡,但也會產(chǎn)生新的對象技術(shù)?;蛟S更好的理解和掌握函數(shù),類型系統(tǒng)才是真正掌握對象技術(shù)的捷徑,也未可知。

本文通過對對象技術(shù)和函數(shù)技術(shù)的介紹,闡述了作者的觀點,其實并不存在,誰會取代誰的說法,這只是如何看待面向?qū)ο蠹夹g(shù)的問題。希望對你會有幫助。

【編輯推薦】

  1. 面向?qū)ο缶幊蘋OP已死 有事燒紙
  2. 軟件設(shè)計師:關(guān)于面向?qū)ο蟮囊恍┧伎?/span>
  3. JavaScript面向?qū)ο缶幊蹋涸屠^承實例
  4. 基于面向?qū)ο螅∣O)的數(shù)據(jù)庫設(shè)計模式探討
責(zé)任編輯:于鐵 來源: InfoQ
相關(guān)推薦

2011-04-02 09:07:46

OOP

2011-01-07 10:18:28

RSSWeb

2023-02-06 07:37:29

Java編程語言

2022-09-15 10:44:42

SidecarIstioeBPFizer

2021-01-21 08:00:25

JVM

2014-01-06 09:36:53

IT部門BYODBYOA

2012-02-20 10:12:09

Java

2021-01-19 10:58:15

漏洞管理漏洞數(shù)據(jù)泄露

2011-12-07 10:20:19

Email新聞

2015-08-31 10:59:22

2013-01-31 17:23:20

RIM黑莓BB10

2021-04-19 08:17:42

MesosKubernetesLinux

2020-02-29 15:18:10

DevOpsNoOps運維

2024-09-03 09:31:59

2020-02-19 11:35:21

iPhone越獲PP助手

2023-11-15 15:37:21

大模型人工智能

2020-12-15 10:40:14

CentOSRockyLinux

2021-04-27 06:32:23

ERP中臺代碼

2015-04-27 13:42:01

博客社區(qū)數(shù)據(jù)社區(qū)云計算

2010-05-05 09:46:03

NVIDIA摩爾定律
點贊
收藏

51CTO技術(shù)棧公眾號