針對(duì)當(dāng)下熱門的Flutter跨平臺(tái)開(kāi)發(fā)語(yǔ)言蔑滓,Dart語(yǔ)法是其根本末融,所以這里寫(xiě)了一篇關(guān)于Dart語(yǔ)法的文章尝胆,希望可以幫到各位快速入門Dart,覺(jué)得還不錯(cuò)的朋友麻煩動(dòng)動(dòng)手指頭給個(gè)star支持下礁阁,后續(xù)會(huì)出其他相關(guān)的開(kāi)發(fā)教程
Dart語(yǔ)法一天快速入門篇 (Github發(fā)布版本)
針對(duì)當(dāng)下熱門的Flutter跨平臺(tái)開(kāi)發(fā)語(yǔ)言巧号,Dart語(yǔ)法是其根本,所以這里寫(xiě)了一篇關(guān)于Dart語(yǔ)法的文章姥闭,希望可以幫到各位快速入門Dart裂逐,覺(jué)得還不錯(cuò)的朋友麻煩動(dòng)動(dòng)手指頭給個(gè)star支持下原創(chuàng)作教程,后續(xù)會(huì)出其他更多相關(guān)的開(kāi)發(fā)教程
- 作者:SanYeCJS
- github地址:https://github.com/SanYeCJS/Dart-Introductory-Grammar
環(huán)境安裝篇
Dart本地環(huán)境安裝(Mac)
如果本地還沒(méi)安裝homebrew的泣栈,需要先安裝: Homebrew 安裝地址
brew tap dart-lang/dart
brew install dart
升級(jí)版本 brew upgrade dart
vscode 需要安裝 Code runner 和 Dart 兩個(gè)插件
類型
Dart是強(qiáng)大的腳本類語(yǔ)言吕粗,可以不定義變量類型使用var字段(類似JavaScript)侥猩,系統(tǒng)會(huì)自動(dòng)推導(dǎo)該變量類型 好比 var str = 'hello world' 也可以用 String str = 'hello world' , var a = 1和 int a = 1
常量修飾符final和const
const表示值不變,并且一開(kāi)始就需要賦值 final也表示該值不能修改,但可以初始化不賦值檐什,但是只能賦值一次
示例代碼
final a = new DateTime.now(); print(a);
const b = new DateTime.now(); print(b);
數(shù)值類型 String bool List Map類型分析
String(定義) 可以用三個(gè)單引號(hào)或者雙引號(hào)务蝠,可以對(duì)字符串進(jìn)行換行調(diào)整诅需,輸出到控制臺(tái)還是會(huì)按照定義的方式輸出信殊,單引號(hào)或雙引號(hào)的不能這么輸出
String(輸出格式,例如str1= 'a', str2= 'b') 可以使用print('
str2'); 輸出結(jié)果
a b
,另一種拼接方式,可以直接用+號(hào)伞广,例如 print(str1 + str2)數(shù)值類型包括int,double
bool取值true拣帽、false (1或者任何非null類型的都為true)
List,列表相對(duì)來(lái)說(shuō)是支持動(dòng)態(tài)操作的,增(add),刪(removeAt),改(list[0]=null)嚼锄,長(zhǎng)度(length屬性),插入(insert(index, element))
List支持定義泛型减拭,例如
var list = new List<String>();
Map類型,可以直接用var定義区丑,同樣支持泛型定義拧粪, 例如
var map = new Map<String, int>();
類型判斷 is 和 ?沧侥?= 和isEmpty
判斷是否是某個(gè)類型的值, xx is 類型名稱
??= 如果左邊的類型是null ,則將右邊的值賦值給左邊可霎, 好比 int a; a??=10; a的最終結(jié)果就是10
isEmpty判斷字符串是否為空串,如果判斷對(duì)象是null會(huì)報(bào)錯(cuò)宴杀,例 str.isEmpty(屬性不是方法)
類型轉(zhuǎn)換
- Number轉(zhuǎn)String使用toString()
- String轉(zhuǎn)Number使用 parse()
Dart常用屬性以及方法
屬性
- length
- reversed (倒序列表癣朗,輸出對(duì)象是元組)
- isEmpty
- isNotEmpty
- keys 獲取所有的key值 (主要用在字典上)
- values 獲取所有的value值(主要用在字典上)
方法
- toList() 將list對(duì)象轉(zhuǎn)List
- addAll() 拼接數(shù)組
- indexOf() 查到返回索引值,查不到返回-1
- removeAt() 刪除指定索引
- join() 將列表以特定符號(hào)拼接成一個(gè)字符串
- split() 將字符串以特定符號(hào)轉(zhuǎn)成list
- containsValue() 是否包含某個(gè)值
循環(huán)方式
foreach
示例
var list = ['1','2', '3'];
var map = {'name':'zhangsan','age':10};
list.forEach((value){
print("value is $value");
});
map.forEach((key,value){
print("key is $key , value is $value");
});
map
說(shuō)明 :對(duì)list中的元素統(tǒng)一操作旺罢,例如統(tǒng)一加減乘除等
示例代碼
var li = [1, 3, 5];
var newLi = li.map((value){
return value*2;
});
print(newLi);
where條件
示例代碼
var li = [1, 3, 5];
var newLi = li.where((value){
return value >= 3;
});
print(newLi);
any條件
說(shuō)明:判斷是否對(duì)象當(dāng)中有某個(gè)條件成立即返回true旷余,好比列表中大于6的元素是否存在
示例代碼
var li = [1, 3, 5];
var flag = li.any((value){
return value >=6;
});
print(flag);
函數(shù)
注意:函數(shù)的形參可以不指定類型盾致,返回值也是可以不指定的,但是為了規(guī)范寫(xiě)法荣暮,一般還是帶上特定的類型做修飾,例如無(wú)返回使用關(guān)鍵字 void罩驻,形參用強(qiáng)類型限定防止外部參數(shù)傳入任意類型導(dǎo)致出錯(cuò)穗酥。
可選參數(shù) printInfo(String username, [int age]); 可選參數(shù)一般放最后
默認(rèn)參數(shù) printInfo(String username, [sex='男']);
將方法作為參數(shù)傳給函數(shù)(其實(shí)也類似與匿名函數(shù),參考代碼片段二)
代碼片段1
void fn(){
print('fn invoke');
}
void fn2(fnName) {
fnName();
}
main() {
fn2(fn);
}
代碼片段2
var fn = (){
print('hello world');
};
main() {
fn();
}
- 如果函數(shù)的方法體只有一句代碼惠遏,可以用=>代替花括號(hào),以下例子用forEach砾跃,例如:
main() {
var list = ['zhangsan', 'lisi', 'wangwu'];
list.forEach((value)=>print(value));
}
自執(zhí)行函數(shù)
說(shuō)明:實(shí)際為匿名函數(shù)自己調(diào)用
((){
print('123');
})();
閉包
特點(diǎn):能使變量常住內(nèi)存并且不會(huì)污染全局,既有全局變量的特點(diǎn)也有局部變量的特點(diǎn)
main() {
func(){
int a=100;
return (){
a++;
print(a++);
};
}
var func2 = func();
func2();
func2();
func2();
}
類
初始化聲明
可以在生成對(duì)象的同時(shí)初始化內(nèi)部參數(shù)节吮,如下代碼片段:
class Rect {
int width;
int height;
//初始化參數(shù)
Rect():width=10,height=10{}
get area {
return this.width * this.height;
}
set areaWidth(int width) {
this.width = width;
}
}
main() {
Rect rect = new Rect();
print(rect.area);
}
Flutter中生成對(duì)象通常會(huì)省略new關(guān)鍵字抽高,如下代碼片段
var rect = Rect();
//類似flutter中返回widget
return Center();//此處省略了new關(guān)鍵字
默認(rèn)構(gòu)造函數(shù)
默認(rèn)構(gòu)造函數(shù)跟類名一致,如下代碼片段:
class Person{
String name;
int age;
//默認(rèn)構(gòu)造函數(shù)(只能存在一個(gè)默認(rèn)構(gòu)造函數(shù))
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
以上代碼可以簡(jiǎn)寫(xiě)為如下:
class Person{
String name;
int age;
//默認(rèn)構(gòu)造函數(shù)(只能存在一個(gè)默認(rèn)構(gòu)造函數(shù))
// Person(String name, int age) {
// this.name = name;
// this.age = age;
// }
//默認(rèn)構(gòu)造函數(shù)簡(jiǎn)寫(xiě)
Person(this.name, this.age);
}
命名構(gòu)造函數(shù)
一個(gè)類寫(xiě)多個(gè)命名構(gòu)造函數(shù)透绩,寫(xiě)法如下:
class Person{
String name;
int age;
Person.now(String name, int age) {
this.name = name;
this.age = age;
}
Person.now2(String name, int age) {
this.name = name;
this.age = age;
}
}
main() {
Person p = new Person.now('zhangsan', 10);
Person p2 = new Person.now2('lisi', 11);
}
類內(nèi)部的函數(shù)中訪問(wèn)類屬性
class Person{
String name;
int age;
void printInfo(){
//通過(guò)${this.xxx}
print('${this.name} , ${this.age}');
//通過(guò)this.xxx
print(this.name);
//通過(guò)$name
print('$name');
}
}
對(duì)象操作符
- 翘骂?條件運(yùn)算符(如果為空,后續(xù)操作不執(zhí)行帚豪,例如p為null碳竟,調(diào)用getInfo方法,政策執(zhí)行會(huì)報(bào)錯(cuò)狸臣,如果加上p?.getInfo()就不會(huì)調(diào)用了),示例代碼如下:
var p;
//這里調(diào)用報(bào)錯(cuò)莹桅,因?yàn)閜為null
p.getInfo();
//進(jìn)行非空判斷,不會(huì)執(zhí)行g(shù)etInfo方法
p?.getInfo();
- as 類型轉(zhuǎn)換
示例代碼
class Person {
Person(){}
void printInfo(){
print("person test");
}
}
main(){
var p;
p = '';
p = new Person();
(p as Person).printInfo();
}
is 類型判斷(參考以上【類型】章節(jié)的講解第三點(diǎn))
.. 級(jí)聯(lián)操作(連綴,這種語(yǔ)法類似于鏈?zhǔn)椒绞剑?/p>
class Person {
String name;
int age;
Person(){}
void printInfo(){
print("person test");
}
}
main(){
Person p = new Person();
p..name = 'zhangsan'
..age = 10
..printInfo();
}
繼承
關(guān)鍵字extends
例如 class Teacher extends Person{}
表示Teacher類繼承自Person類
調(diào)用父類默認(rèn)的方法 super
class Teacher extends Person {
//此方式調(diào)用父類的默認(rèn)構(gòu)造方法
Teacher(String name, int age): super(name, age);
}
重寫(xiě)父類方法 @override(可以不加,但是一般會(huì)加上)
class Person {
void printInfo(){
print("person test");
}
}
class Teacher extends Person{
//采用關(guān)鍵字@override 標(biāo)記該方法是重寫(xiě)父類的烛亦,這點(diǎn)跟Java一樣
@override
void printInfo() {
super.printInfo();
}
}
抽象類
Dart中的抽象類主要用于定義標(biāo)準(zhǔn)诈泼,這個(gè)跟Java語(yǔ)言有點(diǎn)像,在Dart中煤禽,抽象類也可以作為抽象類接口來(lái)使用铐达, 抽象類通過(guò)關(guān)鍵字 abstract來(lái)定義,如果想作為接口來(lái)使用定義一套標(biāo)準(zhǔn)檬果,可以用關(guān)鍵字 implements來(lái)使用
抽象方法
- Dart中娶桦,抽象方法不能用abstract來(lái)修飾,抽象類中沒(méi)有方法體的方法我們可以稱之為抽象方法
- 如果子類繼承抽象的父類就必須實(shí)現(xiàn)里面的所有抽象方法(也可以說(shuō)是重寫(xiě)所有父類抽象方法汁汗,這里記得是抽象方法衷畦,抽象類可以存在非抽象方法)
- 如果把抽象類作為接口來(lái)使用,就必須實(shí)現(xiàn)所有抽象類里面定義的所有屬性與方法
- 抽象類不能直接被實(shí)例化知牌,只要子類才可以
- 接口更多用于約束和規(guī)范祈争,而抽象類更多用于共用某些方法
示例代碼
//抽象類 繼承的子類必須實(shí)現(xiàn)抽象方法
abstract class A {
printA();
printAA(){
print("AA");
}
}
//接口 實(shí)現(xiàn)該接口必須實(shí)現(xiàn) 方法+屬性
abstract class B {
String name;
printB();
}
class C extends A implements B {
@override
String name;
@override
printA() {
print('A');
}
@override
printB() {
print('B');
}
}
mixins
Dart中有一種方式能實(shí)現(xiàn)類似多繼承,但實(shí)際不是繼承,用關(guān)鍵字with
示例代碼
class A {
void printA(){
}
void getStr(){
print("this is A method");
}
}
class B {
void printB(){
}
void getStr(){
print("this is B method");
}
}
class C with A, B {
@override
void printA() {
print("重寫(xiě)的A方法");
}
@override
void printB() {
print("重寫(xiě)的B方法");
}
}
void main() {
C c = new C();
c.printA();
c.printB();
//A和B均有g(shù)etStr 方法角寸,調(diào)用哪個(gè)方法取決于with之后寫(xiě)的順序有關(guān)菩混,最后一個(gè)會(huì)覆蓋前面所有的
c.getStr();
print(c is A); //true
print(c is B); //true
}
訪問(wèn)修飾符
私有屬性和方法
Dart中沒(méi)有像Java語(yǔ)言中有public忿墅,private,protected這些訪問(wèn)修飾符沮峡,但是我們可以采用下劃線_ 把一個(gè)屬性或者方法定義成私有的疚脐,這一點(diǎn)跟Python的語(yǔ)法很像,但是應(yīng)該注意的一點(diǎn)邢疙,當(dāng)把該聲明了私有方法或?qū)傩詥为?dú)抽離為一個(gè)文件時(shí)棍弄,才生效,好比把Person類放在model目錄下疟游,然后其他文件引用了這個(gè)model呼畸,才變成不能訪問(wèn)的私有屬性和方法
getter和setter修飾符
以下是最原始的代碼片段:
class Rect {
int width;
int height;
Rect(this.width, this.height);
// 簡(jiǎn)單地求面積
int area() {
return this.width * this.height;
}
}
main() {
Rect rect = new Rect(10, 2);
print(rect.area());
}
get 關(guān)鍵字修飾
class Rect {
int width;
int height;
Rect(this.width, this.height);
// 簡(jiǎn)單地求面積 通過(guò)添加get修飾符,可以把a(bǔ)rea函數(shù)變?yōu)閷傩缘脑L問(wèn)方式
get area {
return this.width * this.height;
}
}
main() {
Rect rect = new Rect(10, 2);
//這里通過(guò)屬性的訪問(wèn)方式調(diào)用方法
print(rect.area);
}
set 關(guān)鍵字修飾
class Rect {
int width;
int height;
Rect(this.width, this.height);
// 簡(jiǎn)單地求面積 通過(guò)添加get修飾符颁虐,可以把a(bǔ)rea函數(shù)變?yōu)閷傩缘脑L問(wèn)方式
get area {
return this.width * this.height;
}
set areaWidth(int width) {
this.width = width;
}
}
main() {
Rect rect = new Rect(10, 2);
rect.areaWidth = 100;
//這里通過(guò)屬性的訪問(wèn)方式調(diào)用方法
print(rect.area);
}
static
① 說(shuō)明: 通過(guò)static修飾的屬性和方法蛮原,外部可以通過(guò)類名直接調(diào)用,例如:
Person.name
Person.getInfo()
② static修飾的方法不能訪問(wèn)非static修飾的屬性
泛型
說(shuō)明:泛型是對(duì)類型的限定另绩,例如List這樣就只能傳入字符串類型的數(shù)據(jù)儒陨,List這樣只能傳入int類型的數(shù)據(jù)
示例代碼
main() {
//可以用var也行
List<String> list = new List<String>();
list.add('hello');
list.add('world');
//以下這行代碼報(bào)錯(cuò)
list.add(1);
print(list);
}
Map類型指定泛型的如下
main() {
var map = new Map<String, int>();
map.addAll({'no':1});
//以下這行代碼報(bào)錯(cuò)
map.addAll({'username':'zhangsan'});
print(map);
}
修飾方法
說(shuō)明:修飾方法可以不對(duì)類型進(jìn)行強(qiáng)制檢查,能提高函數(shù)的復(fù)用性
示例代碼
T returnValue<T>(T value) {
return value;
}
main() {
String name = returnValue('zhangsan');
int age = returnValue(10);
print('$name $age');
}
自定義List泛型輸入
class JSList<T> {
var list = new List<T>();
add(T value) {
this.list.add(value);
}
}
main() {
var list = JSList<String>();
list.add('helloworld');
//以下這行代碼報(bào)錯(cuò)笋籽,因?yàn)镴SList限定了輸入類型
list.add(123);
}
泛型配合接口實(shí)現(xiàn)
abstract class A<T> {
printInfo(T value);
}
class B<T> implements A<T> {
@override
printInfo(T value) {
print('這是B的輸出類型');
}
}
class C<T> implements A<T> {
@override
printInfo(T value) {
print('這是C的輸出類型');
}
}
main() {
var b = new B<String>();
var c = new C<int>();
b.printInfo('hello world');
c.printInfo(123);
}