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

Dart中的可選類型是如何工作的

開發(fā) 前端
Dart編程語言中最具創(chuàng)新的特性之一是可選類型的使用。本文件旨在解釋可選類型是如何工作的。

Dart 語言是動態(tài)類型的。你可以編寫、運行沒有類型標注的任何程序,就像你使用Javascript的方式。

51CTO推薦專題:Google Dart新結構化編程語言

你可以在程序中添加類型標注:

◆ 添加類型不會阻止你程序的編譯和運行——即使標注不完整或錯誤。

◆ 不論你添加了什么類型標注,你的程序都具有完全相同的語義。

然而,添加類型標注可以使你獲益。類型提供了下面這些好處:

◆ 給人看的文檔。明智地放置類型標注可以使別人更容易地閱讀你的代碼。

◆ 給機器看的文檔。工具可以有多種方式利用類型標注。特別是,它們可以在 IDE 中幫助提供很好的特性,如名稱補全和增強的導航。

◆ 早期的錯誤檢測。Dart 提供了靜態(tài)檢查器,它可以警告你潛在的問題,而不用你自己查。另外,在開發(fā)模式中,Dart 自動把類型標注轉換為運行時斷言檢查來輔助調試。

◆ 有時,在編譯到 Javascript 時,類型可以幫助改進性能。

靜態(tài)檢查器

靜態(tài)檢查器(static checker)行為很像C中的鏈接。它在編譯時警告你潛在的問題。這些警告中的很多是和類型相關的。靜態(tài)檢查器不會產(chǎn)生錯誤——不論檢查器說什么你總是可以編譯和運行你的代碼。

檢查器不會對每個可能的類型違反都敏感。它不是類型檢查器(typechecker),因為Dart并不是按照典型的類型系統(tǒng)那樣使用類型。檢查器會抱怨那些非??赡苁钦鎸崋栴}的地方,而不會強迫你去滿足心胸狹隘的類型系統(tǒng)。

例如,考慮這個:

  1. String s1 = '9';  
  2. String s2 = '1';  
  3. ...  
  4. int n = s1 + s2;  
  5. print(n); 

這里明顯是個問題。這種情況下靜態(tài)檢查器會產(chǎn)生一個警告。注意代碼依然可以運行,n 被置為字符串'91'并打印出來。

然而,不像典型的強類型系統(tǒng),這樣的代碼:

  1. Object lookup(String key) {...} // a lookup method in a heterogenous table  
  2. String s = lookup('Frankenstein'); 

檢查器不會抱怨。因為這種情況下代碼很有可能是對的,雖然缺少類型信息。你作為程序員通常知道程序的語義,而類型檢查器(typechecker)不知道。你知道'Frankenstein'這個key在表中存儲的是字符串,即使 lookup 方法聲明返回的是Object。

Dynamic類型

沒有提供類型的時候,Dart如何避免抱怨呢?這其中的關鍵就是 Dynamic 類型,這是程序員沒有明確給出類型時候的默認類型。使用 Dynamic 類型讓檢查器閉嘴。

偶爾,你可能想要明確地使用 Dynamic 。

  1. Map<String, Dynamic> m = {  
  2.     'one': new Partridge(),  
  3.     'two': new TurtleDove(),  
  4.     ...,  
  5.     'twelve': new Drummer()}; 

我們本來也可以給m使用 Map<String, Object> ,但是那樣的話,當我們獲取內容的時候,它們將是Object的靜態(tài)類型,而它只有很少的信息。因為map的內容除了Object外沒有公共的super接口,我們可能更愿意使用 Dynamic 。如果我們像這樣調用map 的值的方法:

  1. pearTree = m['one'].container(); 

如果內容是Object類型,我們會得到警告,因為Object不支持container方法。如果我們使用Dynamic類型,就不會產(chǎn)生警告。

范型

Dart 支持具體化范型(reified generics)。就是說,范型類型的對象在運行時攜帶它們的類型參數(shù)。傳遞類型參數(shù)給范型類型的構造函數(shù)是運行時操作。這如何與可選類型的要求相一致呢?

好吧,如果你不想總是考慮類型,范型并不強迫你。你可以創(chuàng)建范型類的實例,而不需要提供類型參數(shù)。例如,這樣寫沒問題:

  1. new List(); 

當然,如果你想要,也可以這樣寫:

  1. new List<String>();  
  2. new List(); 

是下面這樣的快捷方式:

  1. new List<Dynamic>(); 

在構造函數(shù)中,類型參數(shù)起到運行時角色。實際上,它們在運行時被傳遞,所以你可以做動態(tài)類型測試的時候使用它們。

  1. new List<String>() is List<Object>  // true: every string is an object   
  2. new List<Object>() is List<String>  // false: not all objects are strings 

Dart中的范型符合程序員的直覺。這是一些更有趣的情況:

  1. new List<String>() is List<int>     // false  
  2. new List<String>() is List          // true  
  3. new List<String>() is List<Dynamic> // same as line above  
  4. new List() is List<Dynamic>         // true, these are exactly the same  

與此相反,類型標注(例如變量前添加的類型或者函數(shù)和方法的返回類型)起到非運行時角色并且不影響程序的語義。***一個值得學習的情況:

  1. new List() is List<String>          // true as well! 

你可以不用類型寫程序,但是你經(jīng)常要傳遞數(shù)據(jù)到有類型的庫中。為了防止類型妨礙你,沒有類型參數(shù)的范型類型被認為是任何其它范型類型的替代品(子類型)。

檢查模式

在開發(fā)過程中,Dart 程序可以在檢查模式(checked mode)下運行。如果你在檢查模式下運行程序,在參數(shù)傳遞、返回結果和執(zhí)行賦值時,系統(tǒng)將自動執(zhí)行某些類型的檢查。如果檢查失敗,程序將在該處停止執(zhí)行,并帶有清晰的錯誤信息。所以,

  1. String s = new Object(); 

將會停止執(zhí)行,因為Object不是String的子類型。然而,

  1. Object foo(){return "x";}  
  2. String s = foo(); 

工作正常,因為foo在運行時返回的實際對象就是String,盡管其類型簽名說foo返回的是Object。當對象賦值給變量時,Dart 檢查對象的運行時類型是否為變量(靜態(tài))聲明類型的子類型。

本質上,檢查模式就像是在對每次賦值、返回等進行子類型檢查的調試器下運行。一些更復雜的例子:

  1. <int>[0,1, 1][2] = new Object(); // fails in checked mode  
  2.    
  3. bar(int n) { return n *2;}  
  4. ...  
  5. bar(3.2); // returns 6.4 in production, but fails in checked mode 

在檢查模式下,每次把參數(shù)傳遞給函數(shù)時,都要檢查參數(shù)的運行時類型是否是形式參數(shù)聲明類型的子類型。我們可以很容易地糾正這個:

  1. bar(num n) { return n *2;}  
  2. ...  
  3. bar(3.2); // works fine  
  4.    
  5. int i_bar(num n) { return n *2;}  
  6. ...  
  7. i_bar(3.2); // fails in checked mode  
  8.             // because returned value is not an int 

注意***一行。檢查發(fā)生在返回值上,即使函數(shù)的結果并沒有進行賦值。

讓我們回到之前的Frankenstein例子上。

  1. Object lookup(String key) {...} // a lookup method in a heterogenous table  
  2. String s = lookup('Frankenstein'); 

如果我們假設的lookup方法返回一個String是正確的,那么檢查模式會平滑地執(zhí)行。如果不是,那么它將捕獲到我們的這個錯誤。在生產(chǎn)模式(production mode)下,代碼都會運行,不會抱怨。假設lookup方法真的返回了一個非String對象,一個Frankenstein類的實例。那么變量 s 將容納那個實例。Dart 絕不會神奇地強制它為一個字符串。如果Dart那樣做就會意味著類型標注正在改變我們程序的行為,類型就不再是可選的了。

當然,如果你根本就不用類型,檢查模式不會妨礙你。

  1. my_add(s1, s2) { return s1 + s2;}  
  2.    
  3. my_add(3, 4); // 7  
  4. my_add("3", "4"); // "34" 

所有這些檢查會帶來很大的性能損失,所以通常不能用在生產(chǎn)環(huán)境中。這些檢查的好處是它們可以在源頭上捕獲動態(tài)類型的錯誤,更容易地調試問題。雖然總可以在測試過程中發(fā)現(xiàn)大多數(shù)這類問題,但是檢查模式有利于縮小它們的范圍。

使用類型

如何使用類型取決于你。如果你討厭類型,你不必使用它們。你不會得到任何類型的警告,你可以用你在其它動態(tài)語言中感到舒適的方式開發(fā)。然而你依然可以從類型中獲益,因為Dart的庫中有類型簽名,它們告訴你它們期望什么和返回什么。如果你在檢查模式中運行,傳遞了錯誤的參數(shù)給類庫,檢查模式將在你犯錯的地方發(fā)現(xiàn)它們。

如果你喜歡類型,你可以在任何地方使用它們,很像是靜態(tài)類型語言。然而,即使那樣你也不會獲得同樣級別的靜態(tài)檢查。Dart的規(guī)則比較寬松。我們期望為這些人提供額外的工具來更加嚴格地解釋類型標注。

我們不建議太極端地使用方式。應該在有意義的地方使用類型。你能做的最有價值的事情是添加類型到你類庫中公有成員的聲明上。接下來,再對私有成員做同樣的事。即使沒有別人需要維護代碼,如果你離開代碼幾周或幾個月后又回來,你會發(fā)現(xiàn)它是有幫助的。在這兩種情況下,你不一定要在方法體或函數(shù)體中添加類型。庫的使用者從類型簽名中獲得價值,即使它們不是100%準確。

在函數(shù)體中,并不總是需要標注聲明。有時代碼足夠簡單,真的無所謂,類型反而可能會造成混亂。

通常,你應該設計代碼,別讓考慮類型影響你。在某些情況下,有幾種替代的設計,其中的某種比其它更適合使用類型。例如,你可以用傳遞函數(shù)替代它,而不是用傳遞字符串表示要調用的函數(shù)名,這樣代碼會更有效并更容易檢查類型。Dart 同樣防止以其他方式無端地使用反射(reflection)。然而,當真正有意義時,你應該毫不猶豫地使用反射。

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

【編輯推薦】

  1. Dart語言慣用語——Dart中特有的代碼味道
  2. 瞬間秒殺所有人的Dart語言版Hello World
  3. Dart VS JavaScript之JavaScript的先天殘疾
  4. Google新結構化編程語言Dart可運行在Jvm上
  5. 眾家評說谷歌新編程語言Dart
責任編輯:陳貽新 來源: 韓國愷的博客
相關推薦

2017-11-17 09:13:31

Java注解

2022-09-16 00:11:45

PyTorch神經(jīng)網(wǎng)絡存儲

2022-05-18 08:00:00

JavaScriptFetch數(shù)據(jù)

2022-04-14 09:01:39

React源碼Flow

2024-01-16 07:33:02

SwiftTypeScript可選綁定

2011-08-08 13:45:58

jQuery

2021-05-10 17:20:55

AIOps開發(fā)人員人工智能

2024-07-19 08:00:00

深度學習知識蒸餾

2023-01-31 16:43:31

?Node.js事件循環(huán)

2023-03-06 00:27:02

Kubernetesscheduler系統(tǒng)

2021-08-03 14:29:30

ARPANET互聯(lián)網(wǎng)協(xié)議TCP

2023-04-18 14:53:48

2023-04-18 15:09:50

2010-08-02 16:56:03

ICMP協(xié)議

2024-09-06 17:55:27

Springboot開發(fā)

2015-09-02 10:33:54

紅包類型optionals

2023-04-19 08:13:02

EpollLinux

2022-08-08 08:00:00

人工智能機器學習計算機應用

2024-02-22 08:00:00

SoraOpenAI

2022-08-12 07:00:00

NFC安全性RFID
點贊
收藏

51CTO技術棧公眾號