聊聊Built-in type、Records、Collections

前言
今天大概會說說一些算是蠻基礎的型別問題,不過型別大概就是那幾種,這幾次會先聊聊Built-in type、Records、Collections這幾個類型在官網上的寫法,稍微看完語法之後覺得好像Dart的語言蠻好用的欸(!
正文
The Dart language has special support for the following:
- Numbers (
int
,double
) - Strings (
String
) - Booleans (
bool
) - Records (
(value1, value2)
) - Lists (
List
, also known as arrays) - Sets (
Set
) - Maps (
Map
) - Runes (
Runes
; often replaced by thecharacters
API) - Symbols (
Symbol
) - The value
null
(Null
)
上面的資料來源是Dart官網上的描述,其實從第一語言是Swift的學習者的角度來看,大概只會對幾個語法比較有疑問,大概會是這樣:Records、Maps、Runes、Symbols,在這個篇章裡面大概也會針對這幾個可能比較特殊的Type去進行比較多的描述。
然後,在Dart語法上,也有幾個比較特別的案例:
Some other types also have special roles in the Dart language:
Object
: The superclass of all Dart classes exceptNull
.Enum
: The superclass of all enums.Future
andStream
: Used in asynchrony support.Iterable
: Used in for-in loops and in synchronous generator functions.Never
: Indicates that an expression can never successfully finish evaluating. Most often used for functions that always throw an exception.dynamic
: Indicates that you want to disable static checking. Usually you should useObject
orObject?
instead.void
: Indicates that a value is never used. Often used as a return type.
上面也是官網定義的,或許還沒進到Dart Style的物件導向時,可以先來看看這些型別有什麼特殊的意義。
數字Numbers
在Dart語言中,所有的數字都是Object型別的階層,以它為基本的型別去延伸出兩個我們在Swift中也看得到的語言型別:int、double
int這個型別通常都是64位元,那原則上也是看是使用什麼平台去編譯,官網上就有這個描述:
- On native platforms, values can be from -263 to 263–1.
- On the web, integer values are represented as JavaScript numbers (64-bit floating-point values with no fractional part) and can be from -253 to 253–1.
不過,由於Dart的設計本身就是具有跨平台的特質,所以可以在Mobile上跟Web進行編譯,不過在兩個平台上本身就具有差異,如果你可以看官網對於Dart對於數字上的文件規範,大抵上就可以知道在int、Double兩個型別上轉換的相關邏輯,還有哪些可能在Mobile上會有什麼表示,哪些可能在Web上怎麼表示,那這邊就不贅述這些細節,傅傳送門給大家。
字串String
其實字串可能真的沒有什麼好特別描述的,其實邏輯真的跟Swift大同小異:
var somthing = "Something"
然後如果是遇到需要數字或其他的型別在字串裡面的話,會這樣寫:
const aConstNum = 0;
const aConstBool = false;
const aConstString = 'a constant string';
const validConstString = '$aConstNum $aConstBool $aConstString';
好像蠻實用的R,不過在字串轉換成數字這點可能會更常用,所以可以稍微在這邊記錄一下:
// 下面是字串轉成int
var one = int.parse('1');
// 下面是字串轉成double
var oneParse = double.parse('1.1')
// int轉成字串
String oneAsString = 1.toString()
// double轉成字串
String piAsString = 3.14159.toStringFixed(2);
Runes
關於這個型別,其實就是所謂的Unicode編碼,我們可以使用這種編碼去創建一個圖案,像是官網上就有舉例:
import 'package:characters/characters.dart';
void main() {
var hi = 'Hi 🇩🇰';
print(hi);
print('The end of the string: ${hi.substring(hi.length - 1)}');
print('The last character: ${hi.characters.last}');
}
上面這樣印出來就會是:
dart run bin/main.dart
Hi 🇩🇰
The end of the string: ???
The last character: 🇩🇰
不過像是上面也有舉個例,如果我們給的Unicode沒有完整,它就識別不出來這樣的字串
基本上Runes就是個在Swift裡面也有個概念,這邊就點到為止。
記錄Record
記錄算是一種匿名、不可變的聚合類型,據說和有一種型別叫做Collection有一樣的概念,它可以把很多的物集綁在一起物件中。
那在語法上,可能會這樣表示:
var record = ('first',a: 2, b: true, 'last');
//或者下面這樣
(String, int) record;
record = ('A string',123);
哦,好像還可以寫的更細一點:
({int a, int b}) record;
record = (a: 123, b: true);
({int a, int b}) recordAB = (a:1, b:2);
({int x, int y}) recordXY = (x:3, y:4);
Record這個語法還有個不錯用的寫法:
var record = ('first', a: 2, b: true, lost);
/// 那如果我要調用出第一個record裡面的值,我可以這樣寫:
print(record.$1); /// 這個會印出first
print(record.a); /// 這個會印出2
print(record.b); /// 這個會印出3
print(record.$2); /// 這個會印出lost
看起來就是針對Record的內容去做出設定,用$position的方式去調出值來。
Record也有另一種寫法,但這種寫法就跟上一種不一樣,不會給與它像是Key的概念使用,但直接以$position的方式就還是可以調出這個儲存的值。
(num, Object)pair = (42, 'a');
var first = pair.$1
var second = pair.$2
看起來好像真的比Swift的字典還要好用,下面還有另一種用法,叫做Record equlity,大概語法像下面這樣:
(int x, int y, int z)point = (1, 2, 3);
(int r, int g, int b) color = (1, 2, 3);
//我們可以利用這個語法特性去做是否等於的判斷:
print(point == color); //這樣會印出true
然後,如果要回傳多個值的話,可以像下面這樣寫:
(String, int) userInfo(Map<String, dynamic>json) {
return (json['name'] as String, json['age'] as int);
}
final json = <String, dynamic> {
'name': 'Dash',
'age': 10,
'color': 'blue'
};
//這邊就可以把它轉成Record來用
var (name, age) = userInfo(json);
//那接下來就可以像上面的用法來組合了!
Record真的跟dictionary非常相似,不過看起來樂趣跟變化度也比較高,可能會花一點時間轉換一下,那接下來會談到的語法是Collections。
Collection
collection大概看起來有分成四大類,一是List、二是Sets、三是Maps,還有Operators
List大概不用太多著墨,在Swift中就是所謂的Array,大概就可以這樣寫:
var list = ["影山", "小", "麥機"];
//如果要數量可以這樣要:
print(list.length == 3); // 這邊應該會回true吧
//如果要讀取某個順序裡面的值:
print(list[0] == "影山"); // 這邊應該也會回true吧
總之特性大概就是有序、可索引、可計算長度。
Set
那有另一個很像的叫做Sets,其實跟Swift的Set一樣,就是不會排序,官方網站有提到unordered、unique items,意味著每一個set裡面的東西都是獨一無二的。
舉個例子:
var example = { '路易莎', '星巴克', '金色三麥'};
如果是要開一個空的Set,請這樣寫:
var names = <String>{};
//或先宣告型別
Set<String> names = {};
// 但如果你這樣寫:
var names = {};
//上面這會是個map,不是set
那如果要操作Set的使用,可以用add()或addAll()
var elements = <String>()
elements.add('name');
//如果可能要加一整個坨的東西
elements.addAll(example);
其實大概邏輯就跟Swift在使用Set的時候是用insert去新增資料一樣。
Maps
不過剛剛上面有提到一個跟Set很像的Maps,它跟Swift中的Dictionary就真的很相近,或者乾脆說就是一樣的東西:
Key-Value的特性:
var people = {
'Mark': '18',
'May': '18'
'Bob': '18'
};
//那如果要加value進去呢?
people['Dan'] = '33';
如果要創建一個在編譯時期就不會改變的map,可以這樣寫:
final constantMap = const {
2: 'HHH',
10: 'Gan',
20: 'FFF',
};
Operators
那這樣還有另一種方式去呈現很多的東西,這在Swift裡也有:
var list = [1, 2, 3];
var list2 = [0, ...list];
list2.lenght == 4 ///這樣會回true
///上面這樣就會有四個值
//如果list有可能是null值
//那就會是這樣
var list2 = [0, ...?list];
Dart有另一個蠻方便的語法,叫做Control Flow Operators
它可以讓你在list裡面放if 或 for,這個語法真的讓Swift使用者的我有點興奮R
來示範一下:
var city = ['Taipei', 'Taichung', 'Hsinchu', if (condition)'Tainan'];
//如果condition為true,就會新增Tainan
//如果condition為false,就會是['Taipei', 'Taichung', 'Hsinchu']而已
var city = ['Taipei', 'Taichung', 'Hsinchu',if (login case 'City')'Tainan']
// 這個則是條件變數如果有City,就會新增Tainan
// 沒有就是['Taipei', 'Taichung', 'Hsinchu']三者
//下面是配for in 的作法
var name = ['Joe', 'Bryan', 'Landis']
var listOfString = ['#0', for (var i in name)'#$i'];
print(listOfString)
//上面這樣print,結果應該會是#0、#Joe、#Bryan、#Landis
看來Dart在使用上真的有蠻多特別的地方,我覺得蠻方便的XD
稍微瀏覽了一下這幾個算式蠻基礎的語法,對於之後可能的開發,稍微有點興奮的想像了。
後記
下一個章節會描述的會是Generics、Typedefs、Type System。如果我哪個地方可能不求甚解了,可以提醒我一下。
最近梅雨季來,好想騎車R。
這個月結束,希望自己可以騎大三元,真正的來個長距離的挑戰,也許之後會稍微記錄一下自己騎車的始末,也許寫個Blog來聊聊一個莫名踏入自行車世界的歷程吧。