聲明
本筆記是我自己在學習Dart語言基礎的時候做的筆記。有些代碼只是爲了演示用法,不要糾結邏輯。
本筆記是站在一個Android開發者的角度上記錄的,Dart中與Java相同的地方沒有做記錄,請諒解。閱讀本筆記將默認你是一個Android或Java開發者。
一、聲明變量與常量
Dart中聲明變量有以下幾種方式:
//第一種方式
var str = '這是字符串';
var str2 = "這是字符串2";
var str3 = '''
這是字符串3
這是字符串3的第二行
''';
var str4 = """
這是字符串4
這是字符串4的第二行
""";
var age = 24;
//第二種方式
String str = '這是字符串';
int age = 25;
Dart中的常量使用final
和const
關鍵字修飾,const
定義時就要賦值,final
可以使用時在賦值,final
也是運行時常量,在運行時也不能被修改。
//使用final定義。
final String name = '李四';
final int age = 24;
//使用const定義。
const String gender = '男';
const int height = 165;
二、自定義函數
1. 可選參數
可選參數的作用就類似Java語言中的方法重載。
/**
* 定義可選參數的自定義函數。
* @userName 爲必傳參數。
* @age 可選參數
*/
String printUserInfo(String userName, [int age]){
return "姓名:$userName-年齡:${age==null??"未知"}";
}
//調用演示
print(printUserInfo("張三"));
print(printUserInfo("李四", 24));
//輸出結果
姓名:張三-年齡:未知
姓名:李四-年齡:24
2. 可選參數-帶默認值
可選參數也支持賦值默認值,也就是說,如果調用方法的時候沒有傳該參數,那麼就就會使用默認值賦值。
/**
* 定義可選參數的自定義函數。
* @userName 爲必傳參數。
* @gander 可選參數
* @age 可選參數
*/
String printUserInfo(String userName, [String gender='男', int age]){
return "姓名:$userName-性別:$gender-年齡:${age==null??"未知"}";
}
//調用演示
print(printUserInfo("張三"));
print(printUserInfo("小微", '女'));
//輸出結果
姓名:張三-性別:男-年齡:未知
姓名:小微-性別:女-年齡:未知
3. 命名參數
命名參數幾乎和可選參數一樣,只是有以下兩點不同:
1).寫法不同,要將[]
中括號換成{}
花括號。
2).用法不同,可選參數在調用時必須按照方法中聲明的順序傳參,而命名參數則不需要按照順序。這是因爲命名參數在傳參時必須制定參數名。
/**
* 定義命名參數的自定義函數。
* @userName 爲必傳參數。
* @gander 可選參數
* @age 可選參數
*/
String printUserInfo(String userName, {String gender='男', int age=23}){
return "姓名:$userName-性別:$gender-年齡:$age";
}
//調用演示
print(printUserInfo("張三", age:20));
print(printUserInfo("小微", age:18, gender:'女'));
//輸出結果
姓名:張三-性別:男-年齡:20
姓名:小微-性別:女-年齡:18
4. 把方法做爲參數
其實就是參數類型爲一個Function。
//第一種方式
void fn1(fn){
fn();
}
void fn2(){
print('這裏是方法2');
}
//調用演示
fn1(fn2);
//第二種方式
var fn3 = (){
print('這裏是方法3');
};
//調用演示
fn1(fn3);
//輸出結果
這裏是方法2
這裏是方法3
5. 匿名函數
//無參匿名方法
var fun1 = (){
print('無參匿名方法');
};
//有參匿名方法
var fun2 = (String arg){
print(arg);
};
三、類
1. 權限修飾符
Dart語言中並沒有像Java一樣有public
、private
、protected
這些權限修飾符。Dart中只有一個權限修飾符_
(下劃線)。下劃線修飾符類似於Java中的默認修飾符,在同一個.dart文件中是公開的,不同的.dart文件中是私有的。
class Persion{
//私有成員變量姓名。
String _name;
//私有成員變量年齡
int _age;
//構造方法
Persion(String name, int age){
_init(name, age);
}
//私有init方法。
void _init(String name, int age){
this._name = name;
this._age = age;
}
//公共方法獲取姓名。
String getName(){
return this._name;
}
//公共方法獲取年齡。
int getAge(){
return this._age;
}
}
2. 構造方法
1). 默認的構造方法與Java一樣,但Dart支持可選參數
2).命名構造
命名構造顧名思義就是給構造方法定義一個名字,在使用的時候直接使用這個名字即可,其實在使用時的代碼看起來更像是Java中的靜態方法,只是在靜態方法中返回了這個對象而已。
class Persion{
String name;
int age;
/**
* 定義命名構造
*/
Persion.create(String name, int age){
this.name = name;
this.age = age;
}
}
//使用
var persion = Persion.create("張三", 23);
print("${persion.name}-${persion.age}")
//輸出
張三-23
3. getter 和 setter 方法
Dart中的方法與Java中的方法一樣,在調用時後面必須要跟上()
,比如persion.getName()
,但是使用get或set定義方法後就可以像成員變量一樣使用。
class Persion{
String _name;
int _age;
/**
* 定義命名構造
*/
Persion(String name, int age){
this._name = name;
this._age = age;
}
get isBaby{
return this._age <= 2;
}
set age(int age){
this._age = age;
}
}
//使用
var persion = new Persion('張三', 23);
persion.age = 1;
print(persion.isBaby);
//輸出
true
4. 初始化列表
在Dart中我們可以在構造方法執行之前初始化對象的變量。
class Persion{
String name;
int age;
/**
* 定義命名構造
*/
Persion(): this.name = '李四', this.age = 24{
}
}
//使用
var persion = new Persion();
print("${persion.name}-${persion.age}");
//輸出
李四-24
5. 靜態屬性和靜態方法
Dart中的靜態屬性和靜態方法與Java中一致,靜態方法中不能訪問非靜態成員,非靜態方法中可以訪問靜態成員。
class Persion{
static String name = '王五';
static int age = 25;
static isBaby(){
return age <= 2;
}
}
//使用
print("${Persion.name}-${Persion.age}-${Persion.isBaby()}");
//輸出
王五-25-false
6. 對象操作符
-
?
條件運算符var persion persion?.getName() //加上 ? 表示如果persion爲null則不會getName方法,相當於非null判斷。
as
類型轉換符(強轉)is
類型判斷(相當於Java中的instanceOf)-
..
級聯操作(連綴)class Persion{ String name; int age; void printInfo(){ print("$name-$age"); } } //使用 Persion persion = new Persion(); persion..name = '趙六' ..age = 36 ..printInfo(); //輸出 趙六-26
7. 繼承
Dart中關於繼承的規則基本和Java一致。
class Persion{
String name;
int age;
Persion(String name, int age){
this.name = name;
this.age = age;
}
void printInfo(){
print("$name-$age");
}
}
class Man extends Persion{
Man(String name, int age) : super(name, age);//如果父類沒有空參構造子類就必須要調用父類的構造。
}
//使用
var man = new Man('如花', 28)
man.printInfo()
//輸出
如花-28
上面的代碼是正常的繼承關係,下面是被繼承的類有命名構造。
class Persion{
String name;
int age;
Persion.create(String name, int age){
this.name = name;
this.age = age;
}
void printInfo(){
print("$name-$age");
}
}
class Man extends Persion{
Man(String name, int age) : super.create(name, age);//調用super的命名構造。
}
複寫父類方法。
class Man extends Persion{
Man(String name, int age) : super.create(name, age);
//覆蓋父類的方法
@override
void printInfo() {
print('我是一個男人');
}
}
其他的基本與Java一致,這裏就不再詳細記錄了。
四、抽象類&接口
Dart中的抽象類充當了Java中的接口和抽象類,Dart中可以子類可以繼承抽象類也可以實現抽象類接口。由於Dart中沒有interface關鍵字所以定義接口時推薦使用抽象類,只是子類實現時不是使用extends
而是使用implements
。
1. 抽象類
abstract class Fruits{
String taste();
}
class Apple extends Fruits{
String name;
Apple(String this.name);
@override
String taste() {
return "${name}蘋果又甜又脆";
}
}
//使用
Fruits fruits = new Apple("紅富士");
print(fruits.taste());
//輸出
紅富士蘋果又甜又脆
2. 接口
接口使用implements
關鍵字而不是extends
:
abstract class Fruits{
String taste();
}
class Apple implements Fruits{
String name;
Apple(String this.name);
@override
String taste() {
return "${name}蘋果又甜又脆";
}
}
class Durian implements Fruits{
@override
String taste() {
return '榴蓮味道臭臭的但喫起來香';
}
}
//使用
Fruits fruits = new Apple("煙臺");
print(fruits.taste());
fruits = new Durian();
print(fruits.taste());
//輸出
煙臺蘋果又甜又脆
榴蓮味道臭臭的但喫起來香
使用implements
關鍵字實現和extends
繼承,有什麼區別?答案是,如果是用implements
的話,那麼接口中的所有方法子類都必須要複寫。如果使用extends
則只需要複寫抽象方法即可。由此可以說明以下兩點:
- 一個類到底是接口還是抽象類還是普通類,得看子類使用的是
extends
繼承還是implements
實現。 - 抽象類中可以有抽象方法,也可以有非抽象方法,什麼樣的方法是抽象方法?沒有方法體的方法就是抽象方法。
注意,Dart與Java一樣,只可以多實現不可以多繼承。
3. mixins混合類
混合類其實是一個類似多繼承的這麼一個功能。爲什麼說類似多繼承?因爲從代碼上看,它確實很像多繼承。但使用mixins還有以下幾個條件:
- 做爲mixins的類只能繼承自Object,不能繼承其他類。
- 做爲mixins的類不能有構造函數。
- 一個類可以mixins多個mixins類。
- mixins絕不是繼承,也不是接口,而是Dart語言的一種全新的特性。
class Persion{
void work(){
print('人類都需要工作');
}
}
class ET{
void address(){
print('外星人生活在其他星球');
}
}
//mixins混合類。
class A with Persion, ET {}
//使用
var a = new A();
//混合類a即有Persion的方法又有ET的方法。其實就是class A,把這兩個類給混合在了一起。
a.work();
a.address();
//輸出
人類都需要工作
外星人生活在其他星球
對混合類使用is
進行類型判斷的時候,會滿足它所混合的所有類。
var a = new A();
print(a is Persion);
print(a is ET);
//輸出
true
true
五、泛型
Dart中的泛型與Java中的泛型在使用上基本沒有什麼區別。只是有一點暫時不是很清楚,那就是不知道Dart中有沒有類型擦除的概念。寫demo是發現使用泛型後傳入不同類型的數據在運行時會報錯,不知道這是不是意味着Dart語言沒有類型擦除。關於類型擦除以後再來研究,以後再來補齊這裏的資料。
六、庫
每一個.dart文件就是一個庫。
1. 系統庫
import 'dart:convert';
import 'dart:io';
2. 自定義庫
impot 'lib/Persion.dart';
3. 三方庫
Pub包管理系統中的庫。
三方庫的使用方法有以下幾步:
需要在自己的項目的根目錄中創建一個pubspec.yaml文件。
在pubspec.yaml文件中配置三方庫的名稱、描述、依賴等信息。
運行 pub get 命令將三方庫下載到本地。
-
在項目中要使用的.dart文件中引入三方庫,例如:
import 'package:http/http.dart' as http;
4. 庫的重命名
在導入的不同的庫中存在相同名稱的類時,直接使用類將會報錯,因爲編譯器不知道你要使用的是哪個類,這時就需要用到庫的重命名功能(導包時使用as
爲庫重命名)。
import 'persion1.dart';
import 'persion1.dart' as p2;
main(){
//構建persion1庫中的Persion對象。
Persion persion = new Persion();
//構建persion2庫中的Persion對象。
p2.Persion persion2 = p2.Persion();
}
七、同步異步
調用異步方法要使用await
關鍵字,而await
關鍵字必須在async
的方法中使用。async
就是把方法變成異步方法,await
就是等待異步方法執行完成。
main(List<String> args) async {
var reqServer = await HttpServer.bind('192.168.0.100', 8080);
print('服務已啓動');
await for (HttpRequest req in reqServer) {
handleMessage(req);
}
}