日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Dart語(yǔ)言慣用語(yǔ)——Dart中特有的代碼味道

對(duì)于其它語(yǔ)言,特別是Java和Javascript的開(kāi)發(fā)者,Dart語(yǔ)言設(shè)計(jì)得看起來(lái)很熟悉。如果你足夠努力,你可以使 Dart 就像是那些語(yǔ)言一樣。如果你非常努力,你甚至可以把Dart變?yōu)镕ortran,但是這樣你將錯(cuò)過(guò)Dart中獨(dú)特的、有趣的部分。

創(chuàng)新互聯(lián)為企業(yè)級(jí)客戶提高一站式互聯(lián)網(wǎng)+設(shè)計(jì)服務(wù),主要包括網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、App定制開(kāi)發(fā)、微信小程序定制開(kāi)發(fā)、宣傳片制作、LOGO設(shè)計(jì)等,幫助客戶快速提升營(yíng)銷能力和企業(yè)形象,創(chuàng)新互聯(lián)各部門(mén)都有經(jīng)驗(yàn)豐富的經(jīng)驗(yàn),可以確保每一個(gè)作品的質(zhì)量和創(chuàng)作周期,同時(shí)每年都有很多新員工加入,為我們帶來(lái)大量新的創(chuàng)意。 

推薦專題:Google Dart新結(jié)構(gòu)化編程語(yǔ)言

本文將幫助您寫(xiě)出適用于Dart的獨(dú)特代碼。因?yàn)檎Z(yǔ)言仍在演進(jìn)中,所以這里的許多慣用語(yǔ)也在變化。語(yǔ)言中的有些地方我們?nèi)圆淮_定用什么***實(shí)踐好。(也許你能幫助我們。)但這里是一些要點(diǎn),有助于把你帶出Java或Javascript的思維慣式,進(jìn)入Dart。

構(gòu)造函數(shù)

本文將從每個(gè)對(duì)象生命周期的起始: 使用構(gòu)造函數(shù)開(kāi)始。每個(gè)對(duì)象都將在某一個(gè)時(shí)刻被構(gòu)造出來(lái),定義構(gòu)造函數(shù)是創(chuàng)建一個(gè)類的重要組成部分。這里Dart有些有趣的想法。

自動(dòng)初始化字段

首先是擺脫一些單調(diào)乏味的部分。許多構(gòu)造函數(shù)僅僅是簡(jiǎn)單地把參數(shù)賦值給字段,如:

 
 
 
  1. class Point {  
  2.   num x, y;  
  3.   Point(num x, num y) {  
  4.     this.x = x;  
  5.     this.y = y;  
  6.   }  

這樣我們這里不得不輸入4次x,僅僅是初始化一個(gè)字段。太爛了。我們可以做的更好:

 
 
 
  1. class Point {  
  2.   num x, y;  
  3.   Point(this.x, this.y);  

在參數(shù)列表中,如果參數(shù)前使用 this. ,那么這個(gè)名字的字段將自動(dòng)使用該參數(shù)值做初始化。這個(gè)例子也展示了另外一個(gè)小特性:如果一個(gè)構(gòu)造函數(shù)體完全是空的,那么可以只使用一個(gè)分號(hào)(;)替代 { }。

命名構(gòu)造函數(shù)

就像大部分動(dòng)態(tài)類型語(yǔ)言一樣,Dart不支持重載。對(duì)于方法而言,這沒(méi)有多少限制,因?yàn)槟憧偸强梢允褂貌煌拿郑菢?gòu)造函數(shù)就沒(méi)有這么幸運(yùn)了。為了緩和這種情況,Dart允許你定義命名構(gòu)造函數(shù):

 
 
 
  1. class Point {  
  2.   num x, y;  
  3.   Point(this.x, this.y);  
  4.   Point.zero() : x = 0, y = 0;  
  5.   Point.polar(num theta, num radius) {  
  6.     x = Math.cos(theta) * radius;  
  7.     y = Math.sin(theta) * radius;  
  8.   }  

這里這個(gè) Point 類有三個(gè)構(gòu)造函數(shù),一個(gè)標(biāo)準(zhǔn)的和二個(gè)命名的。你可以像下面這樣使用它們:

 
 
 
  1. var a = new Point(1, 2);  
  2. var b = new Point.zero();  
  3. var c = new Point.polar(Math.PI, 4.0); 

注意我們這里在調(diào)用命名構(gòu)造函數(shù)的時(shí)候仍然使用了 new 。這樣它就不是一個(gè)靜態(tài)方法了。

工廠構(gòu)造函數(shù)

有一些和工廠(factory)相關(guān)的設(shè)計(jì)模式。當(dāng)你需要一些類的實(shí)例,但是想以更靈活一點(diǎn)的方式,而不是直接用硬編碼的方式調(diào)用具體類型的構(gòu)造函數(shù)的話,這時(shí)這些工廠模式開(kāi)始發(fā)揮作用了。如果你已經(jīng)有了一個(gè)實(shí)例也許會(huì)想返回之前已經(jīng)緩存的實(shí)例,或者也許你想返回一個(gè)不同類型的對(duì)象。

Dart支持這種模式,但不要求你改變創(chuàng)建對(duì)象時(shí)的樣子。而是讓你定義一個(gè)工廠構(gòu)造函數(shù)。當(dāng)你調(diào)用它的時(shí)候看起來(lái)像一個(gè)普通的構(gòu)造函數(shù)。但是實(shí)現(xiàn)可以做任何它想做的事情。例如:

 
 
 
  1. class Symbol {  
  2.   final String name;  
  3.   static Map _cache;  
  4.    
  5.   factory Symbol(String name) {  
  6.     if (_cache == null) {  
  7.       _cache = {};  
  8.     }  
  9.    
  10.     if (_cache.containsKey(name)) {  
  11.       return _cache[name];  
  12.     } else {  
  13.       final symbol = new Symbol._internal(name);  
  14.       _cache[name] = symbol;  
  15.       return symbol;  
  16.     }  
  17.   }  
  18.    
  19.   Symbol._internal(this.name);  

這里我們有一個(gè)表示符號(hào)的類。一個(gè)符號(hào)就像一個(gè)字符串,但是我們保證在任意時(shí)間點(diǎn)上一個(gè)給定的名字只會(huì)有一個(gè)符號(hào)對(duì)象。這讓你能安全地比較兩個(gè)對(duì)象的相等性僅僅通過(guò)測(cè)試他們是同一個(gè)對(duì)象。

這里的默認(rèn)(未命名)構(gòu)造函數(shù)前加上了 factory 前綴。它告訴Dart這是一個(gè)工廠構(gòu)造函數(shù)。當(dāng)它被調(diào)用時(shí),它不會(huì)創(chuàng)建一個(gè)新對(duì)象。(工廠構(gòu)造函數(shù)中沒(méi)有 this 對(duì)象)。相反,期望你創(chuàng)建一個(gè)實(shí)例并明確地返回它。這里我們用給定的名字查找之前緩存的對(duì)象,如果找到了就重用它。

最酷的是調(diào)用者根本看不到這點(diǎn)。它們只需要:

 
 
 
  1. var a = new Symbol('something');  
  2. var b = new Symbol('something'); 

第二個(gè) new 將返回之前緩存的對(duì)象。這很好,因?yàn)檫@意味著如果我們起初不需要工廠構(gòu)造函數(shù)但之后又認(rèn)識(shí)到需要時(shí),我們將不必把所有之前使用new的地方都改為使用靜態(tài)方法調(diào)用。

函數(shù)

像大部分現(xiàn)代語(yǔ)言一樣,函數(shù)是Dart中的頭等公民(first-class),帶有完整的閉包和輕量型語(yǔ)法支持。函數(shù)就像任何其它對(duì)象一樣,你應(yīng)毫不猶豫地自由使用它們。特別是,在Dart團(tuán)隊(duì)中我們大量使用函數(shù)用作事件處理器(event handler)。

Dart有三種創(chuàng)建函數(shù)的表示法:一個(gè)是命名函數(shù),一個(gè)是帶函數(shù)體的匿名函數(shù)和一個(gè)表達(dá)式語(yǔ)句函數(shù)。命名形式看起來(lái)像這樣:

 
 
 
  1. void sayGreeting(String salutation, String name) {  
  2.   final greeting = '$salutation $name';  
  3.   print(greeting);  

這看起來(lái)像是一個(gè)普通的C語(yǔ)言函數(shù)或者Java、Javascript中的方法。和C、C++不同的是,這些可以嵌入到另一個(gè)函數(shù)的中間。如果你不需要給出函數(shù)的名字,也可以使用匿名形式。和上面代碼類似,但沒(méi)有名字或返回類型,像這樣:

 
 
 
  1. window.on.click.add((event) {  
  2.   print('You clicked the window.');  
  3. }) 

這里我們傳遞一個(gè)函數(shù)到add()方法注冊(cè)一個(gè)事件處理器。***,如果你需要一個(gè)真正的輕量型函數(shù),僅僅對(duì)單一表達(dá)式求值并返回,使用 => :

 
 
 
  1. var items = [1, 2, 3, 4, 5];  
  2. var odd = items.filter((i) => i % 2 == 1);  
  3. print(odd); // [1, 3, 5] 

一個(gè)括號(hào)的參數(shù)列表,跟著一個(gè) => 和一個(gè)單一表達(dá)式就創(chuàng)建了一個(gè)帶參數(shù)并返回表達(dá)式結(jié)果的函數(shù)。

實(shí)際上,只要有可能我們自己更喜歡用這種箭頭函數(shù),因?yàn)樗?jiǎn)潔且容易識(shí)別,感謝 => 。我們經(jīng)常使用匿名函數(shù)作為事件處理器和回調(diào)函數(shù)。命名函數(shù)反而使用很少。

Dart 還有一個(gè)技巧,這是我最喜歡的語(yǔ)言特性之一:可以使用 => 定義成員。當(dāng)然,你可以這樣做:

 
 
 
  1. class Rectangle {  
  2.   num width, height;  
  3.    
  4.   bool contains(num x, num y) {  
  5.     return (x < width) && (y < height);  
  6.   }  
  7.    
  8.   num area() {  
  9.     return width * height;  
  10.   }  

但是當(dāng)你僅需要下面這樣做的時(shí)候,為什么還需要上面那樣呢:

 
 
 
  1. class Rectangle {  
  2.   num width, height;  
  3.   bool contains(num x, num y) => (x < width) && (y < height);  
  4.   num area() => width * height;  

我們發(fā)現(xiàn)箭頭函數(shù)非常適用于定義簡(jiǎn)單的getter和其它單行方法來(lái)實(shí)現(xiàn)計(jì)算或訪問(wèn)對(duì)象屬性。

#p#

字段,getters 和 setters

說(shuō)到屬性,Dart使用標(biāo)準(zhǔn)的 object.someProperty 語(yǔ)法使用它們。 當(dāng)屬性是類中一個(gè)真實(shí)的字段時(shí),大部分語(yǔ)言就是這樣做的。但是Dart 還允許你定義一些方法,它們看起來(lái)像是訪問(wèn)屬性,但實(shí)際上可以執(zhí)行任意你想要的代碼。在其它語(yǔ)言中,這些被稱為getters 和 setters。看這個(gè)例子:

 
 
 
  1. class Rectangle {  
  2.   num left, top, width, height;  
  3.    
  4.   num get right()           => left + width;  
  5.       set right(num value)  => left = value - width;  
  6.   num get bottom()          => top + height;  
  7.       set bottom(num value) => top = value - height;  
  8.    
  9.   Rectangle(this.left, this.top, this.width, this.height);  

這里我們定義了一個(gè)Rectangle 類,它有四個(gè)真實(shí)的字段:left, top, width, 和 height。它還有兩對(duì)getters 和 setters方法定義了兩個(gè)額外的邏輯屬性:right 和 bottom。在你使用這個(gè)類時(shí),真實(shí)字段與 getters和setters 沒(méi)有明顯的區(qū)別:

 
 
 
  1. var rect = new Rectangle(3, 4, 20, 15);  
  2. print(rect.left);  
  3. print(rect.bottom);  
  4. rect.top = 6;  
  5. rect.right = 12; 

字段和getters/setters間的模糊化是語(yǔ)言的基本原則??创钋宄姆绞骄褪钦J(rèn)為字段僅僅是魔法實(shí)現(xiàn)的getters 和 setters。這意味著你可以做些有趣的事情,比如用字段覆蓋繼承的getter方法,或反之。如果接口定義了一個(gè)getter,你可以簡(jiǎn)單地用一個(gè)同名、同類型的字段實(shí)現(xiàn)它。如果字段是可變的(非final),那么它也實(shí)現(xiàn)了接口要求的setter。

實(shí)際上,這意味著你不必防御性地把字段隱藏到getter、setter樣板方法里來(lái)隔離它們,就像你在Java或C#中所做的。如果你有需要暴露的屬性,只需用一個(gè)public的字段。如果你不想它們被修改,只需加上final。

稍后,如果你需要做一些驗(yàn)證或什么其它事情,你隨時(shí)可以用getter和setter代替這個(gè)字段。比如我們想確保 Rectangle類總是有非負(fù)的大小,我們可以把它改為這樣:

 
 
 
  1. class Rectangle {  
  2.   num left, top;  
  3.   num _width, _height;  
  4.    
  5.   num get width() => _width;  
  6.   set width(num value) {  
  7.     if (value < 0) throw 'Width cannot be negative.';  
  8.     _width = value;  
  9.   }  
  10.    
  11.   num get height() => _height;  
  12.   set height(num value) {  
  13.     if (value < 0) throw 'Height cannot be negative.';  
  14.     _height = value;  
  15.   }  
  16.    
  17.   num get right()           => left + width;  
  18.       set right(num value)  => left = value - width;  
  19.   num get bottom()          => top + height;  
  20.       set bottom(num value) => top = value - height;  
  21.    
  22.   Rectangle(this.left, this.top, this._width, this._height);  

現(xiàn)在我們修改這個(gè)類增加了一些驗(yàn)證,但根本不影響那些已經(jīng)使用了它的代碼。

頂層定義

Dart是“純”面向?qū)ο笳Z(yǔ)言,變量中的任何東西都是一個(gè)真正的對(duì)象(沒(méi)有突變的原始類型),并且每個(gè)對(duì)象都是某個(gè)類的實(shí)例。然而它不是教條式的OOP語(yǔ)言。它不要求你把每個(gè)東西都定義在類里。相反,如果你愿意,你可以在頂層自由地定義函數(shù)、變量甚至是getters和setters。

 
 
 
  1. num abs(num value) => value < 0 ? -value : value;  
  2.    
  3. final TWO_PI = Math.PI * 2.0;  
  4.    
  5. int get today() {  
  6.   final date = new Date.now();  
  7.   return date.day;  

即使是那些不要求你把所有東西都放在類或?qū)ο笾械恼Z(yǔ)言,如Javascript,它們一般仍然是用一種命名空間的形式:相同名字的頂層定義會(huì)導(dǎo)致不經(jīng)意的沖突。為解決這個(gè)問(wèn)題,Dart使用一種 library 系統(tǒng),允許你用一個(gè)前綴導(dǎo)入其它庫(kù)中的定義來(lái)消除歧義。這意味著你不應(yīng)該需要防御式地把定義放到類中。

我們?nèi)栽谔剿鬟@實(shí)際意味著我們應(yīng)如何定義庫(kù)。我們的大部分代碼是把定義放到類中的,如Math。很難說(shuō)這僅是我們?cè)谄渌Z(yǔ)言中根深蒂固的習(xí)慣還是說(shuō)對(duì)Dart而言這也是一種好的實(shí)踐方式。我們期待這方面的反饋。

我們確實(shí)有一些使用頂層定義的例子。首先你需要運(yùn)行的main()函數(shù)就是要在頂層定義的。如果你使用DOM,熟悉的document 和 window “變量”實(shí)際上是Dart中頂層定義的getters 。

字符串和插值

Dart有幾種字符串字面值。你可以用單引號(hào)或雙引號(hào),也可以用三引號(hào)的多行字符串:

 
 
 
  1. 'I am a "string"' 
  2. "I'm one too" 
  3.    
  4. '''I'm  
  5. on multiple lines  
  6. '''  
  7.    
  8. """  
  9. As  
  10. am  
  11. I  
  12. """ 

為了構(gòu)造更大的字符串,使用+ 連接它們即可:

 
 
 
  1. var name = 'Fred';  
  2. var salutation = 'Hi';  
  3. var greeting = salutation + ', ' + name; 

但是使用字符串插值會(huì)更快更清晰:

 
 
 
  1. var name = 'Fred';  
  2. var salutation = 'Hi';  
  3. var greeting = '$salutation, $name'; 

在字符串中,一個(gè)美元符號(hào)($)跟著一個(gè)變量將被擴(kuò)展為該變量的值。(如果變量不是字符串將調(diào)用它的toString()方法)。你也可以在大括號(hào)里插入表達(dá)式:

 
 
 
  1. var r = 2;  
  2. print('The area of a circle with radius $r is ${Math.PI * r * r}'); 

操作符

Dart使用你熟悉的C、Java語(yǔ)言里一樣的操作符和優(yōu)先級(jí)。它們會(huì)按你期望的方式工作。而在背后,它們有點(diǎn)特殊。在Dart中,使用操作符的表達(dá)式如1+2,實(shí)際上僅是調(diào)用方法的語(yǔ)法糖。對(duì)于語(yǔ)言,這個(gè)例子看起來(lái)更像是1.+(2) 。

這意味著你也可以為你自己的類型重載(多數(shù))操作符。例如這是一個(gè)Vector 類:

 
 
 
  1. class Vector {  
  2.   num x, y;  
  3.   Vector(this.x, this.y);  
  4.   operator +(Vector other) => new Vector(x + other.x, y + other.y);  

這樣,我們可以使用熟悉的語(yǔ)法形式做向量加法:

 
 
 
  1. var position = new Vector(3, 4);  
  2. var velocity = new Vector(1, 2);  
  3. var newPosition = position + velocity; 

話雖如此,請(qǐng)不要過(guò)度濫用。我們給你汽車的鑰匙,并且相信你不會(huì)掉頭把車開(kāi)到客廳里。

在實(shí)踐上,如果你定義的類型在“現(xiàn)實(shí)世界”中(在黑板上?)經(jīng)常使用操作符,那么它可能是一個(gè)好的操作符重載候選者,如:復(fù)數(shù)、向量、矩陣等。另外,也不一定。自定義操作符的類型一般也應(yīng)該是不可變類型。

注意因?yàn)椴僮鞣{(diào)用實(shí)際上僅僅是方法調(diào)用,它們具有固有的不對(duì)稱性。方法總是在左邊的參數(shù)上獲取。所以當(dāng)你做a+b的時(shí)候,是根據(jù) a 的類型決定其意義的。

相等性

有一類操作符需要特別注意。Dart有兩類相等運(yùn)算符:== 和 !=, 與 === 和 !== 。Javascript開(kāi)發(fā)者應(yīng)該很熟悉,但是這里有點(diǎn)區(qū)別。

== 和 != 做等價(jià)測(cè)試。它們應(yīng)該是你99%的時(shí)候使用的。和Javascript不同,它們不做任何隱式轉(zhuǎn)換,所以它們應(yīng)該像你所期待的那樣的行為。別害怕使用它們。和Java不同,它們適用于任何具有等價(jià)關(guān)系定義的類型。不再需要 someString.equals("something") 這樣了。

你可以為你自己的類型重載 == ,只要它們有意義。你不必重載 != ,Dart 自動(dòng)根據(jù)你的 == 定義做推斷。

其它操作符, === 和 !== 用來(lái)測(cè)試身份。a === b 僅當(dāng) a 和 b 是內(nèi)存中完全相同的對(duì)象時(shí)才返回 true 。默認(rèn)情況下,如果類型沒(méi)有定義有意義的相等操作符,那么 == 調(diào)用將退回到 === 。所以你唯一需要用這個(gè)的時(shí)候是你明確地想要繞過(guò)任何用戶定義的 == 操作符。

原文:http://han.guokai.blog.163.com/blog/static/1367182712011925112734306/


文章標(biāo)題:Dart語(yǔ)言慣用語(yǔ)——Dart中特有的代碼味道
分享鏈接:http://www.dlmjj.cn/article/djgsjsh.html