這篇文章主要講講本人近期對編程語言的理解背稼,對編程語言涉及到的編程方法(范式)上的差異以及產(chǎn)生這種差異的內(nèi)在原因的理解限佩。這次用來做示范的是當(dāng)前普遍被使用的兩門編程語言java逛揩、python季稳。之所以以這兩種語言作為參考沪猴,是因?yàn)檫@兩種語言恰恰能夠代表編程語言的兩個(gè)主要類別辐啄,那就是以java為代表的靜態(tài)語言和以python為代表的動態(tài)語言。靜態(tài)語言家族包括C/C++运嗜、C#则披、java、go等洗出,動態(tài)語言則包括有python、javascript图谷、php等翩活。從規(guī)模上可以看出,這兩種類型的語言都占有著非常大的使用比例便贵,流行程度上難分高小菠镇,應(yīng)用領(lǐng)域都非常廣泛。由于時(shí)間有限承璃,僅就java和python兩種語言作為各自的代表進(jìn)行研究利耍。有不對之處,還請不吝指教。
- 靜態(tài)語言 or 動態(tài)語言
怎么區(qū)分靜態(tài)語言還是動態(tài)語言隘梨?其實(shí)很簡單程癌,先給出一個(gè)淺顯易懂的判斷標(biāo)準(zhǔn):定義變量時(shí),需要聲明變量類型的是靜態(tài)語言轴猎,不需要聲明的則是動態(tài)語言嵌莉。是不是很簡單?那么有人要說了捻脖,你前面提到的C#锐峭、go語言,甚至連新版(JDK9)的java語言中都可以如示例1這樣定義變量可婶,這難道說明它們都是動態(tài)語言沿癞,而并非你之前提到的靜態(tài)語言咯?
var value = 100; //示例1
確實(shí)矛渴,按照上文給出的簡單方法椎扬,則C#、go語言等也許都可以劃入動態(tài)語言陣營了曙旭。然而盗舰,實(shí)則不然,伴隨著人們對動態(tài)特性便利性的重視桂躏,很多語言與時(shí)俱進(jìn)钻趋,都引入了動態(tài)語言的部分特性,連java這種老氣橫秋的語言都在與時(shí)俱進(jìn):)剂习。在此蛮位,需要給出更加準(zhǔn)確的定義才能區(qū)分。我沒有參考教科書或者任何官方解釋鳞绕,僅個(gè)人見解的描述失仁。
靜態(tài)語言是指在編譯期能夠確定變量類型的語言,而動態(tài)語言則是指在運(yùn)行期間才能確定變量類型的語言们何。
利用這個(gè)定義就可以正確判斷到底誰是靜態(tài)語言萄焦,誰是動態(tài)語言了。示例1中的代碼如果是C#冤竹,那么value的類型其實(shí)是在編譯期確定的拂封,這是利用編譯器的類型推導(dǎo)能力實(shí)現(xiàn)的,即通過右值的類型推導(dǎo)出左值value的類型(有興趣研究類型推導(dǎo)的同志可以關(guān)注下類型系統(tǒng)這個(gè)領(lǐng)域)鹦蠕,所以C#還是只能歸為靜態(tài)語言一類冒签。而如果示例1是javascript的代碼,則value的類型是在運(yùn)行期方能確定钟病,因此javascript是動態(tài)語言萧恕。這樣我們就終于能夠區(qū)分清楚了刚梭。
很多同志在判斷靜態(tài)和動態(tài)語言的時(shí)候,經(jīng)常會被另一個(gè)概念所迷惑票唆,那就是強(qiáng)類型和弱類型朴读。他們往往認(rèn)為靜態(tài)語言就是強(qiáng)類型語言,而動態(tài)語言就是弱類型語言惰说。這是一個(gè)嚴(yán)重錯(cuò)誤的認(rèn)識磨德。其實(shí)這個(gè)強(qiáng)弱類型和動靜態(tài)是兩類不相干的概念。比如作為動態(tài)語言的python是強(qiáng)類型的吆视,因?yàn)閜ython的類型不能相互隱式轉(zhuǎn)換典挑,而作為靜態(tài)語言的C/C++語言則是弱類型的,因?yàn)镃/C++語言允許類型進(jìn)行隱式轉(zhuǎn)換(如int轉(zhuǎn)double)啦吧。具體哪些語言屬于什么類型可以見下圖(圖來自網(wǎng)絡(luò))您觉,大家可以自己思考一下為什么java是強(qiáng)類型語言。
- 用python和java編程的“感覺”
相信寫過兩種語言的同志們都會有各自對兩類語言編程風(fēng)格的獨(dú)特體會授滓,從我個(gè)人而言琳水,概括起來,那就是:
python(代表動態(tài)語言):自由靈活般堆,卻神鋒太俊在孝,飄飄乎云端。
java(代表靜態(tài)語言):嚴(yán)謹(jǐn)務(wù)實(shí)淮摔,冗長無趣私沮,膠柱鼓瑟,自縛手腳和橙。
java作為一門工業(yè)化級別的語言仔燕,適合團(tuán)隊(duì)化開發(fā),由此誕生的各種設(shè)計(jì)模式魔招,大大的提高了工業(yè)化生產(chǎn)的效率晰搀。設(shè)計(jì)模式就如同一家大企業(yè)的各種制度,一定程度的緩解了大公司體量所帶來的負(fù)擔(dān)办斑。但同時(shí)也限制了員工們個(gè)人的創(chuàng)造力外恕,減弱了他們認(rèn)知的廣度以及嘗試新鮮事物的好奇心。而python的動態(tài)化特性就完全放開了各類約束乡翅,鼓勵你放飛思想吁讨,寫出簡短精悍、富有想象力的代碼峦朗。但也正是python的這種特點(diǎn),造成了其不適合團(tuán)隊(duì)化排龄、大規(guī)模合作的生產(chǎn)環(huán)境波势,由于缺乏編譯期類型檢查(雖然有擴(kuò)展支持類型檢查工具翎朱,用的很少),將錯(cuò)誤推后到運(yùn)行期尺铣,導(dǎo)致編譯器工具無法對其進(jìn)行靜態(tài)代碼檢查和優(yōu)化拴曲,加劇了調(diào)試和測試的需求。且風(fēng)格過于靈活凛忿,需要輔之以大量的編程規(guī)范澈灼,加大了工作難度。
- 設(shè)計(jì)模式的圍城
每一個(gè)java程序員都會對設(shè)計(jì)模式津津樂道店溢,建立在設(shè)計(jì)模式之上的各類“框架”是java生產(chǎn)力的重要支撐叁熔,脫離了各種方便的java框架,或許很多java程序員瞬間就會無所適從床牧,雙手一攤荣回,表示無能為力了「昕龋可見心软,設(shè)計(jì)模式在java語言的應(yīng)用中占有非常重要的地位。舉個(gè)例子著蛙,Spring是一個(gè)家喻戶曉的j2ee框架删铃,里面最核心的依賴注入和控制反轉(zhuǎn)的理念就是設(shè)計(jì)模式思想的體現(xiàn)。java反射的語言特性為Spring實(shí)現(xiàn)控制反轉(zhuǎn)的技術(shù)機(jī)制踏堡,而工廠模式則為依賴注入提供了思想源泉猎唁。同理Spring對AOP的支持,則是代理模式的應(yīng)用暂吉。這些一定程度上體現(xiàn)出了設(shè)計(jì)模式的威力胖秒。
那么python程序員需要設(shè)計(jì)模式嗎? 讓我們來仔細(xì)思考一下慕的,不妨用python實(shí)現(xiàn)一個(gè)工廠模式和抽象工廠模式看看:
class Human:
pass
class Woman(Human):
pass
class Man(Human):
def a(self):
return 100
factory = {
"man": Man,
"woman": Woman,
"human": Human
}
class Chinese:
pass
class European:
pass
class Dog:
pass
class Pig:
pass
#工廠就這么簡單
man = factory["man"]()
woman = factory["woman"]()
human = factory["human"]()
manFactory = {
"chinese": Chinese,
"european": European
}
animalFactory = {
"dog": Dog,
"pig": Pig
}
#抽象工廠(無非就是工廠的工廠)
abstractFactory = {
"manFactory": manFactory,
"animalFactory": animalFactory
}
...
我們看到了動態(tài)類型的威力阎肝,自由靈活。在這個(gè)例子當(dāng)中肮街,沒有涉及到j(luò)ava中的所謂接口风题、繼承、實(shí)現(xiàn)等實(shí)現(xiàn)工廠模式必須的概念嫉父。其實(shí)沛硅,設(shè)計(jì)模式很大程度上是為了彌補(bǔ)java語言在語言動態(tài)特性不足上的缺陷,大量的設(shè)計(jì)模式相當(dāng)于是給java語言打補(bǔ)丁绕辖。而python則在很大程度上講設(shè)計(jì)模式的思想內(nèi)置到了語言的內(nèi)涵當(dāng)中摇肌,這其中的二三事需要仔細(xì)體會。下面再舉一個(gè)策略模式的例子(也許是個(gè)悲傷的故事):
def loveMeOrHim():
return input("love me or him? ")
def loveMe():
print 'love you too!'
def loveHim():
print 'my best wishes'
def loveNoOne():
print 'all right, we can be good friends'
def firstStrategy(*arg, **argw):
loveMe(arg, argw)
def secondStrategy(*arg, **argw):
loveHim(arg, argw)
def thirdStrategy(*arg, **argw):
loveNoOne(arg, argw)
#由于函數(shù)或類在python中都是first-class的仪际,所以策略模式就是這么簡單
def main():
girlsWord = loveMeOrHim()
if girlsWord == 'you':
solver = firstStrategy
elif girlsWord == 'him':
solver = secondStrategy
else:
solver = thirdStrategy
solver()
main()
為什么這里實(shí)現(xiàn)策略模式很簡單又很直觀呢围小?脫離了java的接口昵骤、實(shí)現(xiàn)、繼承等概念肯适。原因就是python語言將函數(shù)或類作為了first-class的結(jié)構(gòu)变秦,可以理解為函數(shù)和類本身就是一個(gè)值,這個(gè)值可以被傳來傳去框舔,可以被當(dāng)做參數(shù)賦來賦去蹦玫。可以換句話說刘绣,python語言直接就內(nèi)置策略模式樱溉,或者說至少內(nèi)化了策略模式的思想。讀者同志們?nèi)绻信d趣额港,可以將java常見的各種設(shè)計(jì)模式用python實(shí)現(xiàn)一遍饺窿,記住不要一來就設(shè)計(jì)什么接口啊、類啊移斩,最好透過現(xiàn)象看本質(zhì)肚医,先拋棄各種java強(qiáng)加于你的思維定式,再充分利用python語言本身的特性來設(shè)計(jì)實(shí)現(xiàn)(熟悉python的同志都知道向瓷,用python實(shí)現(xiàn)個(gè)AOP又是何其的簡單)肠套,如果你能夠剝?nèi)ジ≡诒砻娴母鞣N塵埃,還能推陳出新猖任,則幾近道矣你稚。
- 結(jié)語
其實(shí)還有很多想說想寫的話,但是我是一個(gè)沒有耐心的人朱躺,一時(shí)心血來潮畢竟無法持久的輸出刁赖,恰如王獻(xiàn)之雪夜訪友。我對編程的興趣也是來去如風(fēng)长搀,不縈于懷的宇弛,興盡則收,或許也是敗筆之源源请。其實(shí)這篇文章通篇廢話枪芒,俱是基礎(chǔ),也就供些年輕人笑讀爾谁尸【俗伲回想韶華不駐,二十六載一晃即過良蛮,所見諸事本皆小道所宿爾抽碌,不提也罷,怎可謂幾近道矣决瞳,羞而大笑货徙。