轉(zhuǎn)自—《Flutter:從入門到實踐》http://gitbook.cn/m/mazi/comp/column?columnId=5cc01cc115a1a10d8cec9e86&utm_source=Raysd001
轉(zhuǎn)載試讀章節(jié),已獲得作者授權(quán)伙窃。
學習一門編程語言宏怔,首先要了解它的歷史和特點啼辣。Dart 是 Google 公司推出的編程語言席赂,于 2011 年就已經(jīng)亮相了滚躯。Dart 也是一門面向?qū)ο蟮恼Z言娇钱,語法和 Java毕匀、C璃岳、JavaScript 很像年缎。所以會 Java 語言悔捶,學習 Dart 一般會快一些。
Dart 里所有的類都可以看成是對象单芜,是單繼承蜕该,動態(tài)類語言≈摒可以進行多平臺開發(fā)堂淡,我們的主角 Flutter 就是基于 Dart 語言編寫的。這樣我們就開始進行 Dart 語言的基礎語法學習扒腕。本文將主要介紹:
- Dart 的特點及簡單介紹
- Dart 的數(shù)據(jù)類型绢淀、操作符、變量常量
- Dart 的運算符瘾腰、流程控制語句
- Dart 的函數(shù)(方法)皆的、類
- Dart 的泛型、接口等
1 Dart 簡單介紹
1.1 為什么要介紹 Dart蹋盆?
Google 計劃未來的 Flutter 將會是移動應用费薄、Web 應用、PC 應用等平臺的跨平臺高性能框架栖雾,也是未來的 Fuchsia 操作系統(tǒng)的主要框架楞抡,而 Flutter 是基于 Dart 編程語言編寫的一個跨平臺框架,所以一些語法是基于 Dart 語法來使用的析藕,學習 Flutter 就要先了解 Dart召廷。
1.2 什么是 Dart?
簡單介紹下 Dart 語言账胧。
Dart 是 Google 公司推出的編程語言竞慢,屬于應用層編程語言,于 2011 年就已經(jīng)亮相了找爱。Dart 也是一門面向?qū)ο蟮恼Z言梗顺,語法和 Java、C车摄、JavaScript 很像寺谤。Dart 里所有的類都可以看成是對象,是單繼承吮播,動態(tài)類語言变屁。Dart 可以進行移動應用、Web應用意狠、服務器應用粟关、PC 應用、物聯(lián)網(wǎng)應用的開發(fā)等等环戈,還在不斷拓展開發(fā)平臺闷板,所以可以說 Dart 在各個平臺領域“無所不能”澎灸。我們的主角 Flutter 就是基于 Dart 語言編寫的。
1.3 Dart 的特性
接下來看下 Dart 的特性遮晚。
- 語法簡單明了性昭,開發(fā)速度快、效率高县遣,學習成本低糜颠。
- 簡單但是功能強大,可以開發(fā) Web萧求、移動端其兴、PC、服務器端夸政、物聯(lián)網(wǎng)等平臺應用元旬。
- 編譯執(zhí)行速度快,擁有自己的 Dart VM守问,在移動端和 Web 上擁有高性能法绵。
- 全平臺語言,可移植酪碘。Dart 類似于中間件語言,可以編譯成不同平臺的原生代碼盐茎,可以很方便地擴展成跨平臺應用語言兴垦,如 Android 和 iOS 平臺。
- 語言的結(jié)構(gòu)融合了 Java字柠、C探越、JavaScrpit 的特點,并結(jié)合 React 響應式編程的思維規(guī)范進行構(gòu)建的一個現(xiàn)代化編程語言窑业。
1.4 Dart 的語法特點
- 面向?qū)ο蟮恼Z言钦幔,一切數(shù)據(jù)類型、API 都是對象常柄,都繼承自 Object 類鲤氢;
- 強類型語言,同時也是動態(tài)類型語言西潘。對不確定類型的可以定義成一個動態(tài)類型卷玉;
- Dart 沒有設置定義訪問域的關(guān)鍵字,如果某個變量或者方法喷市、類的名稱以"_"開頭相种,說明這個變量或者方法、類是私有的品姓,外部不可以調(diào)用使用寝并;
- Dart 有入口函數(shù):main(){...}箫措;類似于Java的public void main(String[] args){...};
- Dart 吸收了很多現(xiàn)代編程語言的特點,加入了很多便捷的語法支持衬潦,可以明顯縮減代碼量和提高可讀性斤蔓;
- 擁有 Future 和 Streams 使用方式,可以進行類似 RxJava 式的使用别渔。
2 Dart 的關(guān)鍵字
好了附迷,說了這么多,接下來該進入正題哎媚,我們來學習一些具體知識喇伯。
首先看下 Dart 的關(guān)鍵字(33 個保留字,17 個內(nèi)置標志符)拨与。
33 個 Dart 保留字:
關(guān)鍵字 | ||||||
---|---|---|---|---|---|---|
assert | break | const | continue | case | catch | class |
default | else | enum | extends | final | finally | false |
for | is | in | new | rethrow | return | superdo |
switch | throw | try | typedef | this | true | var |
void | while | with | typedef | this |
17 個 Dart 內(nèi)置標志符:
關(guān)鍵字 | ||||||
---|---|---|---|---|---|---|
abstract | as | covariant | deferred | dynamic | export | external |
factory | get | implements | import | library | operator | part |
set | static | typedef |
6 個 Dart2 新增異步功能關(guān)鍵字:
關(guān)鍵字 | |||||
---|---|---|---|---|---|
async | async* | await | sync* | yield | yield* |
25 個 Dart 特有關(guān)鍵字(和 Java 語言相比):
關(guān)鍵字 | ||||||
---|---|---|---|---|---|---|
as | assert | async | async* | await | const | covariant |
deferred | dynamic | export | external | factory | get | in |
is | library | operator | part | rethrow | set | sync* |
typedef | var | yield | yield* |
3 Dart 的數(shù)據(jù)類型
我們先看一個官方給的最基礎的 Dart 例子稻据,例如我們新建一個 demo.dart 類:
// 這是程序執(zhí)行的入口
main() {
var number = 30; // 定義變量number并進行賦值初始化
printNumber(number); // 調(diào)用方法
}
// 定義方法printNumber
printNumber(num aNumber) {
print('The number is $aNumber.'); // 在控制臺打印輸出內(nèi)容
}
這個例子涵蓋了 Dart 的一個基礎的語法結(jié)構(gòu),有入口买喧、有變量聲明捻悯、賦值、定義方法淤毛、調(diào)用方法今缚、傳遞參數(shù)、數(shù)據(jù)類型低淡、變量引用等等姓言。
那么接下來我們看下 Dart 支持的幾種基本數(shù)據(jù)類型:numbers(num)、String蔗蹋、bool何荚、List 集合、Map 集合猪杭、runes(用于在字符串中表示 Unicode 字符)餐塘、symbol。
numbers(num)類型是表示數(shù)值型的數(shù)據(jù)類型皂吮,包括 int 和 double 類型兩種戒傻。num 是 int 和 double 類型的父類。其中 int 整數(shù)值一般范圍在 -2^53 和 2^53 之間涮较;double 是 64 位雙精度浮點型數(shù)據(jù)類型稠鼻。舉個例子:
void main() {
//定義int和double類型
int a = 6;
double b = 3.18;
print('$a ,$b');
// String轉(zhuǎn)int
int twoInt = int.parse('2');
// String轉(zhuǎn)double
var twoDouble = double.parse('2.2');
print('$twoInt ,$twoDouble');
// int轉(zhuǎn)String
String intToString = 2.toString();
// double轉(zhuǎn)String,后面需加入保留小數(shù)點位數(shù)
String doubleToString = 3.23456.toStringAsFixed(2);
print('$intToString,$doubleToString');
//自動四舍五入
String fiveString = 2.12832.toStringAsFixed(2);
print(fiveString);
}
輸出結(jié)果為:
6 ,3.18
2 ,2.2
2,3.23
2.13
大家可以在 DartPad 上進行操作:https://dartpad.dartlang.org
String 類型
大家應該都很熟悉狂票,字符串類型候齿。
- Dart 字符串是 UTF-16 編碼的字符序列,可以使用單引號或者雙引號來創(chuàng)建字符串。
- 可以在字符串中使用表達式慌盯,用法是這樣的: ${expression}周霉。
- 可以使用 + 操作符來把多個字符串鏈接為一個,當然也可以不用加號亚皂,多個帶引號的字符串挨著寫就可以了俱箱。
- 使用三個單引號或者雙引號也可以創(chuàng)建多行字符串。
- 使用 r 前綴可以創(chuàng)建一個原始字符串灭必。
再來看一個例子:
void main() {
//單引號和雙引號定義
String singleString = 'A singleString';
String doubleString = "A doubleString";
print('$singleString ,$doubleString');
//使用$字符引用變量狞谱,使用{}引入表達式
String userS = 'It\'s $singleString';
String userExpression = 'It\'s expression,${singleString.toUpperCase()}';
print('$userS');
print('$userExpression');
//使用引號字符串鄰接來拼接或者使用+號連接字符串
String stringLines =
'String ' 'concatenation' " works even over line breaks.";
String addString = 'A and ' + 'B';
print('$stringLines');
print('$addString');
//使用三個引號(單引號或雙引號)來創(chuàng)建多行字符串
String s3 = '''
You can create
multi-line strings like this one.
''';
String s33 = """This is also a
multi-line string.""";
print('$s3');
print('$s33');
//使用r為開頭,顯示定義一個原始字符串
String s = r"It is a \n raw string.";
print('$s');
}
輸出結(jié)果為:
A singleString ,A doubleString
It's A singleString
It's expression,A SINGLESTRING
String concatenation works even over line breaks.
A and B
You can create
multi-line strings like this one.
This is also a
multi-line string.
It is a \n raw string.
bool 類型
用于定義 true 或 false 的數(shù)據(jù)類型禁漓,很簡單跟衅。需要區(qū)別注意的是有些寫法在 Dart 里不支持。
var name = 'Tom';
if (name) {
// JavaScript可以這樣寫播歼,Dart不行
print('He is Tom!');
}
// JavaScript可以這樣寫伶跷,Dart不行
if (1) {
print('A line Data.');
} else {
print('A good Data.');
}
List 集合
Dart 里使用 List 來表示數(shù)據(jù)集合結(jié)構(gòu)。
void main() {
//定義初始化一個集合
var list = [1, 2, 3];
List listData = [5, 6, 7];
print(list.length);
print(list[0]);
//集合數(shù)據(jù)賦值
listData[1] = 8;
print(listData[1]);
//如果在集合前加了const關(guān)鍵字秘狞,集合數(shù)據(jù)不可以進行操作
var constantList = const [1, 2, 3];
List datas = List();
datas.add('data1');
datas.addAll(['data2', 'data3', 'data4', 'data5', 'data6']);
//輸出第一個元素
print(datas.first);
// 獲取最后一個元素
print(datas.last);
// 獲取元素的位置
print(datas.indexOf('data1'));
// 刪除指定位置元素
print(datas.removeAt(2));
//刪除元素
datas.remove('data1');
//刪除最后一個元素
datas.removeLast();
// 刪除指定范圍元素叭莫,含頭不含尾
datas.removeRange(0, 2);
//刪除指定條件的元素
datas.removeWhere((item) => item.length > 3);
// 刪除所有的元素
datas.clear();
//其他方法可以自己嘗試
}
Map 集合
Map 集合存儲數(shù)據(jù)特點就是鍵值對(key-value)形式。key 是唯一的烁试,value 允許重復雇初。看一個實例:
void main() {
//定義一個map并賦值
var gifts = {
// Keys Values
'first': 'dog',
'second': 'cat',
'fifth': 'orange'
};
var nobleGases = {
// Keys Values
2: 'a',
10: 'b',
18: 'b',
};
//定義一個map并賦值
Map map = Map();
map['first'] = 'a-value';
map['second'] = 'b-value';
map['fifth'] = 'c-value';
Map nobleGasesMap = Map();
nobleGasesMap[2] = 'a-value';
nobleGasesMap[10] = 'b-value';
nobleGasesMap[18] = 'c-value';
//指定鍵值對類型
var nobleGases = new Map<int, String>();
//獲取某個key的value
print(map['first']);
//獲取map大小
print(map.length);
//定義一個不可變的map
final constantMap = const {
2: 'a',
10: 'b',
18: 'c',
};
//其他API用法和List類似
}
Runes 類型
表示字符串 Unicode 編碼字符(UTF-32 code points)等减响。
void main() {
//看一個官方例子
var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
}
Symbols 類型
使用 Symbol 字面量來獲取標識符的 symbol 對象抵皱,也就是在標識符前面添加一個 # 符號。
//看一個官方例子
#radix
#bar
4 Dart的操作符
看下 Dart 的操作符:
描述 | 操作符 |
---|---|
一元后綴符(unary postfix) | expr++ ? expr-- ? () ? [] ? . ? ?. |
一元前綴符(unary postfix) | -expr ? !expr ? ~expr ? ++expr ? --expr |
乘法類型(multiplicative) | * ? / ? % ? ~/ |
加法類型(additive) | + ? - |
位操作符(shift) | << ? >> |
按位與(bitwise AND) | & |
按位異或(bitwise XOR) | ^ |
按為或(bitwise OR) | | |
比較和類型測試(relational and type test) | >= ? > ? <= ? < ? as ? is ? is! |
等價(equality) | == ? != |
邏輯與(logical AND) | && |
邏輯或(logical OR) | || |
是否是空(if null) | ?? |
條件運算符(conditional) | expr1 ? expr2 : expr3 |
級聯(lián)運算符(cascade) | .. |
賦值(assignment) | = ? *= ? /= ? ~/= ? %= ? += ? -= ? <<= ? >>= ? &= ? ^= ? |
這些操作符用法和其他語言的含義和用法大同小異辩蛋。
5 Dart 的流程控制語句
Dart 流程控制語句也不多,比較簡單移盆。主要有:
- if 和 else
- for 循環(huán)
- while 和 do-while 循環(huán)
- break 和 continue
- switch 和 case
- assert 斷言(判斷是否相等)
如果其中涉及到使用 try-catch 和 throw悼院,可能會影響一些流程控制的跳轉(zhuǎn)。
void main() {
//if和else
if (hasData()) {
print("hasData");
} else if (hasString()) {
print("hasString");
} else {
print("noStringData");
}
//for循環(huán)
var message = new StringBuffer("Dart is good");
for (var i = 0; i < 6; i++) {
message.write(',');
}
//while
while (okString()) {
print('ok');
}
//do-while
do {
print('okDo');
} while (!hasData());
//break和continue
while (true) {
if (noData()) {
break;
}
if (hasData()) {
continue;
}
doSomething();
}
//switch和case
var command = 'OPEN';
switch (command) {
case 'A':
executeA();
break;
case 'B':
executeB();
break;
case 'C':
executeC();
break;
default:
executeUnknown();
}
//Assert(斷言)
assert(string != null);
assert(number < 80);
assert(urlString.startsWith('https'));
}
Exceptions 異常捕獲處理咒循。
使用 throw 拋出異常据途。
throw new FormatException('Expected at least 2 section');
也可以拋出其他類型對象。
throw 'no data!';
使用 catch 捕獲異常叙甸。
try {
getData();
} on OutOfLlamasException {
sendData();
} on Exception catch (e) {
print('Unknown data Exception: $e');
} catch (e) {
print('Some Exception really unknown: $e');
}
使用 rethrow 可以把捕獲的異常給重新拋出颖医。
//給出一個官方例子
final foo = '';
void misbehave() {
try {
foo = "You can't change a final variable's value.";
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // rethrow重新拋出,允許main()里的函數(shù)繼續(xù)捕獲處理異常
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
Finally 處理裆蒸,和 Java 里的類似熔萧,不管是否出現(xiàn)異常,最終都要執(zhí)行的方法寫在這里。
try {
getData();
} catch(e) {
print('Error: $e');
} finally {
//始終執(zhí)行
sendData();
}
6 Dart 的類和函數(shù)(方法)
類這個概念是面向?qū)ο罄锏姆鹬拢珼art 也依然保留贮缕。我們創(chuàng)建對象需要創(chuàng)建類對象,可以使用 new 關(guān)鍵字俺榆,也可以不使用:
var map=Map();
var map2=new Map();
調(diào)用類方法:
var map=Map();
map.length;
//通過 對象.方法 的形式來調(diào)用使用方法
使用 ?. 來替代 . 可以避免當左邊對象為 null 時拋出異常:
a?.name = 'Tom';
關(guān)于獲取對象的類型感昼,可以使用 Object 的 runtimeType 屬性來獲取實例的類型。
先看一個實例化對象罐脊,并獲取和調(diào)用屬性和方法的例子定嗓,和 Java 用法基本一致:
class Position {
num x;
num y;
methodPosition(){
...
}
}
void main() {
var pos = new Position();
pos.x = 5;//賦值
print(pos.x);//取值
pos.methodPosition();//調(diào)用方法
}
定義同名構(gòu)造方法:
class Position {
num x;
num y;
Position(num x, num y) {
this.x = x;
this.y = y;
}
}
//也可以這樣簡化定義構(gòu)造方法
class Point {
num x;
num y;
Point(this.x, this.y);
}
注意:Dart 的構(gòu)造函數(shù)不可以繼承,父類的構(gòu)造函數(shù)也不可以繼承萍桌。
Dart 也支持抽象函數(shù)(抽象類):
abstract class Dog {
//可以定義變量和抽象方法
void doSomething(); // 定義抽象方法
}
class GoodDog extends Dog {
void doSomething() {
//實現(xiàn)邏輯
}
}
Dart 的類可以繼承多個類宵溅,這個 Dart 的一大特點。Dart 也支持實現(xiàn)多個接口梗夸,使用 implements 關(guān)鍵字:
class Comparable {
final _name;
Comparable(this._name);
String good1(who) => 'Hello';
}
class Location {
Location();
String good2() => 'World!';
}
class ImlClass implements Comparable, Location {
// ...
}
Dart 通過 extends 來繼承拓展類层玲,子類可以重寫父類方法,通過 supper 來引用父類方法反症。
class Product {
void open() {
//...
}
// ...
}
class SmartProduct extends Product {
void open() {
super.open();
//重寫加入新的邏輯
}
// ...
}
//也可以使用@override注解來表示重寫了父類方法
還有其他注解辛块,如可以使用 @proxy 注解來避免警告信息。
Dart 也支持枚舉類型 enum:
enum Color {
red,
green,
blue
}
//使用時候直接調(diào)用
Color.blue
可以使用 with 關(guān)鍵字實現(xiàn)多繼承:
//看一個官方例子
class Musician extends Performer with Musical {
// ...
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
Dart 支持靜態(tài)函數(shù)使用铅碍,使用時候直接類名.函數(shù)名即可润绵。
class Position {
static num getLongPosition() {
return 20;
}
}
void main(){
//直接調(diào)用
Position.getLongPosition();
}
7 Dart 的泛型和限制域
Java 中泛型使用 T 來表示界牡,Dart 里同樣可以使用 T 來表示泛型類型葡盗。
abstract class Dog<T> {
T getDogByName(String name);
setDogByname(String name, T value);
}
//也可以限制泛型繼承自什么類等操作
class Foo<T extends SomeBaseClass> {...}
class Extender extends SomeBaseClass {...}
void main() {
var someBaseClassFoo = new Foo<SomeBaseClass>();
var extenderFoo = new Foo<Extender>();
var foo = new Foo();
}
Dart 的庫的引入和使用:Dart 使用 import 關(guān)鍵字來導入庫和類。
import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';
//如果兩個導入的庫里的類有重名的兼吓,可以使用as關(guān)鍵字
import 'package:utils2/utils2.dart' as utils2;
//也可以只導入庫的一小部分
//只導入foo庫
import 'package:lib1/lib1.dart' show foo;
//除了foo烦绳,其他的都導入
import 'package:lib2/lib2.dart' hide foo;
//延遲載入庫卿捎,可以減少APP啟動時間,優(yōu)化性能
import 'package:deferred/hello.dart' deferred as hello;
//延遲后径密,使用的時候使用loadLibrary()來調(diào)用
//在一個庫上可以多次調(diào)用loadLibrary() 函數(shù),只執(zhí)行載入一次
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
如果我們想自己創(chuàng)建聲明一個庫想被別人引用時候午阵,可以用 library 聲明:
// 聲明庫,名字為abc
library abc;
// 導入需要用到的相關(guān)庫
import 'dart:html';
//編寫邏輯
...
//如果需要的話享扔,可以借助part關(guān)鍵字來實現(xiàn)部分需求
如果你想聲明某個變量底桂、常量、方法函數(shù)不能被外部調(diào)用惧眠,只需要在名字前加上 _ 下劃線前綴即可籽懦。
8 Dart 的異步處理
Dart 支持異步編程操作,例如我們的網(wǎng)絡請求氛魁、耗時操作都可以使用暮顺√ǎ可以使用 async 和 await 關(guān)鍵字來進行標識異步操作。
Dart 里也有 Future 和 Stream 對象進行異步操作拖云,非常的強大和方便贷笛。
//例如用await來表示這個方法異步的,需要等待完成后才能繼續(xù)執(zhí)行后面的方法
await lookUpVersion()
//要使用 await宙项,其方法必須帶有 async 關(guān)鍵字:
checkVersion() async {
var version = await lookUpVersion();
if (version == expectedVersion) {
//執(zhí)行操作
} else {
//執(zhí)行操作
}
}
//我們也可以使用Future來修飾包轉(zhuǎn)返回類型乏苦,這樣我們可以支持數(shù)據(jù)的后續(xù)其他操作
Future<String> lookUpVersion() async => '1.6.0';
在 await 表達式中,表達式的返回值通常是一個 Future 類型尤筐;如果返回的值不是 Future汇荐,則 Dart 會自動把該值放到 Future 中返回。
Dart 的基礎語法知識部分就大概這么多盆繁,還有很多細節(jié)掀淘,大家有興趣可以進行深入研究使用方法。
總結(jié)
本文主要是給大家講解 Dart 的基礎語法部分油昂,為后續(xù) Flutter 的開發(fā)學習奠定基礎革娄,以期更好地進行深入研究和開發(fā)。Dart 的語法比較簡單冕碟,和 Java 類似拦惋,可以對照著理解,全面詳細地學習用法后安寺,可以為高效開發(fā)做好準備厕妖。主要注意點和建議如下:
- 建議將例子進行編寫實踐下,使用開發(fā)工具輸出下結(jié)果加深理解挑庶;
- 學習完后言秸,可以進行一個實踐練習。