變數
變數的宣告以及賦值:
//如果不初始化,則後續可以賦值任意型別,最終型別是dynamic型別,dynamic型別不會檢測成員
var name = "Bozo";
複製程式碼
在宣告變數的時候,也可以選擇使用具體的資料型別:
//使用確定型別定義變數,賦值必須是相同型別
String name = "bozo";
int age = 12;
double height = 176.3;
bool onLine = true;
複製程式碼
沒有初始化變數預設值都為
null
,即使變數型別為bool
或者int
Dart中的基本資料型別:num
、double
、int
、String
、List
、Set
、String
、map
、bool
、runes
、Symbol
、Object
、dynamic
Dart中所有資料型別都是物件,都繼承自
Object
類,null
也繼承自Object
類
const&final
使用const
跟final
定義的變數都只能賦值一次,並且在宣告的時候必須進行初始化。
使用const
定義的集合都是隻讀的,特性會傳遞到子元素,在記憶體中會複用相同內容物件,而final
則不會作用於子元素,在記憶體中也不會複用相同物件
//不可以通過 list[0] = 5; 來修改集合中元素的值, 如果換做final來定義則可以修改
const list = [1,2,3,4];
const list2 = [1,2,3,4];
//此時輸出的結果為 true, 如果集合是用final定義的則輸出結果為 false
print(identical(list, list2));
複製程式碼
例項變數可以為
final
但是不能是const
方法
方法可以賦值給變數,也可以當作其他方法的引數,以下為定義方法的示例:
bool isEmpty(String str){
return str == null || str == "";
}
//可以忽略型別定義
isEmpty(str){
return str == null || str == "";
}
//如果是隻有一個表示式的方法,則可以使用縮寫語法來定義
isEmpty(str) => str == null || str == "";
複製程式碼
在Dart中方法還可以設定可選引數,以及設定預設值
void main() {
printInfo("Bozo", 13, true);
//可選位置引數
// printInfo("Bozo", false);
//可選命名引數
// printInfo(name: "Bozo", showAge: false);
//指定預設值
// printInfo(name: "Bozo", showAge: true);
}
printInfo(name, age, showAge) {
if (showAge) {
print("name:$name,age:$age");
} else {
print("name:$name");
}
}
//可選位置引數
printInfo(name, showAge, [age]) {
......
}
//可選命名引數
printInfo({name, age, showAge}) {
......
}
//指定預設值
printInfo({name, age = 12, showAge}) {
......
}
複製程式碼
所有函式都有一個返回值,如果沒有指定返回值,則預設把
return null;
作為函式得最後一個語句執行
操作符
操作符過載
以下操作符可以被過載
例如重寫+
跟-
操作符
class Vector{
final int x;
final int y;
Vector(this.x, this.y);
Vector operator +(Vector v){
return Vector(x + v.x, y + v.y);
}
Vector operator -(Vector v){
return Vector(x - v.x, y - v.y);
}
}
void main(){
Vector v1 = Vector(4, 3);
Vector v2 = Vector(2, 1);
Vector v3 = v1 - v2;
Vector v4 = v1 + v3;
//print: v3:x=2,y:2
print("v3:x=${v3.x.toString()},y:${v3.y.toString()}");
//print: v4:x=6,y:5
print("v4:x=${v4.x.toString()},y:${v4.y.toString()}");
}
複製程式碼
如果覆寫的操作符是
==
,則還應覆寫物件的hashCode
getter 函式
型別判定操作符
as
、is
、is!
操作符是在執行時判定物件型別的操作符
操作符 | 解釋 |
---|---|
as | 型別轉換 |
is | 如果物件是指定的型別返回true |
is! | 如果物件是指定的型別返回false |
級聯操作符
級聯操作符 (..
) 可以在同一個物件上 連續呼叫多個函式以及訪問成員變數,使用級聯操作符可以避免建立 臨時變數
void main() {
Person()
..name = 'bozo'
..age = 12
..contact = (new Contact()
..phoneNumber = '126854315'
..email = 'bozo@gmail.com')
..showInfo();
}
class Person {
String name;
int age;
Contact contact;
showInfo() {
print("Name:${this.name},Age:${this.age},PhoneNumber:${this.contact.phoneNumber},Email:${this.contact.email}");
}
}
class Contact {
String phoneNumber;
String email;
}
複製程式碼
異常
丟擲異常
throw new FormatException('Expected at least 1 section!');
//還可以丟擲任意物件
throw 'Out of llamas!'
複製程式碼
捕獲異常
try {
throwExceptionsFuc();
} on FormatException {
...
} on Exception catch (e) {
...
} catch (e) {
...
} finally {
...
}
}
複製程式碼
可以使用
on
或者catch
來宣告捕獲語句,也可以同時使用。使用on
來指定異常型別,使用catch
來捕獲異常物件,函式catch
可以有一個或兩個引數,第一個引數為丟擲的異常物件,第二個為堆疊資訊
還可以使用rethrow
關鍵字來把捕獲的異常重新丟擲
try{
testFuc();
} catch (e) {
...
//重新丟擲異常
rethrow;
}
複製程式碼
類
Dart中每個物件都是一個類的例項,所有類都繼承於Object
。
建構函式
在Dart中可以使用this
關鍵字來簡化建構函式的實現:
class Person{
String name;
int age;
//原始寫法
Person(String name, int age){
this.name = name;
this.age = age;
}
//使用this關鍵字簡化寫法
Person(this.name, this.age);
}
複製程式碼
如果沒有定義建構函式,跟Java中一樣會有一個預設的無參構造
使用命名建構函式
可以為一個類實現多個建構函式,如果要在一個建構函式中呼叫其他建構函式則使用重定向建構函式
。
void main() {
Person person1 = new Person("Bozo", 17);
Map map = new Map();
map['name'] = "bozo";
map['age'] = 18;
Person person2 = new Person.fromMap(map);
}
class Person {
String name;
int age;
Person(this.name, this.age);
//命名建構函式
Person.fromMap(Map map) {
this.name = map['name'];
this.age = map['age'];
}
//重定向建構函式
Person.byName(name) : this(name, 0);
}
複製程式碼
如果要類提供一個狀態不變的物件,則可以把物件定義為編譯時常量。需要定義一個const
建構函式,並且宣告所有的變數為final
。使用常量構造函建立的物件具有複用性,前提是物件的成員變數值相同。
class Car {
final String color;
const Car(this.color);
static final Car car = const Car("red");
}
void main(){
Car car1 = const Car("red");
Car car2 = const Car("black");
//斷言執行通過,car1跟car為同一個物件
assert(identical(car1, Car.car));
//斷言執行失敗
assert(identical(car2, Car.car));
}
複製程式碼
如果一個建構函式不是總是返回一個新的物件,則可以使用factory
關鍵字來建立工廠方法建構函式
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to the _ in front
// of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = new Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) {
print(msg);
}
}
}
void main(){
var logger = new Logger('UI');
logger.log('Button clicked');
}
複製程式碼
工廠方法無法訪問
this
extends 跟 implements
-
extends
:繼承其他類的屬性以及方法,在dart中可以使用with
關鍵字來實現多繼承class A extends B with C,D{ ... } 複製程式碼
-
implements
:一個類可以通過implements
關鍵字來實現一個或者多個介面, 並實現每個介面定義的 API
列舉
使用 enum
關鍵字來定義列舉型別,列舉中每個值都有一個index
的屬性(從0開始)。列舉的values
常量可以返回所有的列舉值
enum Color{
RED,
GREEN,
BLUE
}
void main(){
List<Color> colors = Color.values;
assert(colors[2] == Color.BLUE);
}
複製程式碼
泛型
在Dart中使用泛型的方式與Java類似:
abstract class Cache<T>{
T getByKey(String key);
void cacheByKey(String key, T value);
}
複製程式碼
限制泛型的具體型別:
class SomeClass<T extends SomeBaseClases>{
...
}
複製程式碼
泛型函式:
T findByIndex<T>(List<T> data, int index) {
return data == null ? data[index] : null;
}
複製程式碼
庫
使用 import
來匯入庫
//內建庫使用 dart:scheme
import 'dart:io';
//其他庫使用檔案系統路徑或者 package:scheme
import 'package:libs/utils.dart';
複製程式碼
如果匯入的兩個庫具有衝突的識別符號,則可以使用庫的字首來區分,例如lib1跟lib2中都存在名為SomeClass的類:
import 'package:libs/lib1.dart';
import 'package:libs/lib2.dart' as lib2;
...
SomeClass class1 = new SomeClass();
lib2.SomeClass class2 = new lib2.SomeClass();
複製程式碼
如果只想匯入庫的一部分內容可以使用 show
跟 hide
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
複製程式碼
如果要讓一個庫在使用的時候才載入則可以使用延時載入庫。如:
//使用 deferred as 匯入
import 'package:deferred/hello.dart' deferred as hello;
//當需要使用的時候,使用庫識別符號呼叫loadLibrary()函式來載入庫
hello.loadLibrary();
hello.sayHello();
複製程式碼
- 一個庫可以呼叫
loadLibrary()
函式,但該庫只會載入一次- 延遲載入庫的常量在匯入的時候是不可用的。 只有當庫載入完畢的時候,庫中常量才可以使用。
- 在匯入檔案的時候無法使用延遲庫中的型別。 如果你需要使用型別,則考慮把介面型別移動到另外一個庫中, 讓兩個庫都分別匯入這個介面庫。
- Dart 隱含的把
loadLibrary()
函式匯入到使用deferred as *的名稱空間*
中。loadLibrary()
方法返回一個 Future。
非同步
非同步方法的宣告是新增 async
關鍵字,如:
...
checkVersion() async{
...
}
複製程式碼
使用await來等待非同步方法返回:
...
//要使用 await,其方法必須帶有 async 關鍵字
checkVersion() async{
var version = await getVersionInfo();
...
}
複製程式碼