1、開發(fā)準備
1.1 Dart 中文官網(wǎng)
1.2 Win10下環(huán)境搭建
1.2.1 如果安裝了Flutter-SDK,其實也可以直接使用里面的dart - sdk


1.2.2 如果之前沒有安裝 Flutter-SDK,請看如下步驟(在線方式)
安裝 包管理器 chocolatey
- 點擊右下級角的開始按鈕,輸入 cmd ,選擇以管理員權(quán)限運行

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
- 輸入如下命令
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

- 檢測安裝是否成功
choco -v

安裝 dart-sdk
choco install dart-sdk
choco upgrade dart-sdk
1.2.3 離線方式安裝,直接下載壓縮包
1.3 開發(fā)工具選擇
IntelliJ IDEA (以這個為例)
Android Studio
其它
1.4 插件的安裝
在線方式



離線方式
-
查看跟IDEA對應的插件版本
image.png 去插件官網(wǎng)查找對應的版本
https://plugins.jetbrains.com/plugin/6351-dart/versions

1.5 項目創(chuàng)建


- 運行出現(xiàn)報錯:Setting VM flags failed: Unrecognized flags: checked

-
把 Checked mode 勾取消即可
image.png

2、數(shù)據(jù)類型
2.1 變量與常量
變量
使用var聲明變量,可賦予不同類型的值
未初始化時,默認值為null
使用fianl聲明一個只能賦值一次的變量

常量
使用const聲明常量
使用const聲明的必須是編譯期常量
-
const 與 final有著本質(zhì)的區(qū)別
1)在定義const常量時,你必須直接賦一個字面量,而不能是一個變量或者公式;
2)在定義final常量時,如何賦值就無所謂了,但賦值后就不能再改了

2.2 內(nèi)置類型
2.2.1 數(shù)值型-Number
Int 整型
double 浮點型

數(shù)值型操作
- 運算符: +、 -、 *、 /、 ~/、 %

- 常用屬性:isNaN、 isEven、 isOdd等


-
常用方法:abs()、round()、floor()、ceil()、toInt()、toDouble()
image.png
2.2.2 字符串-String
字符串創(chuàng)建
使用單引號,雙引號創(chuàng)建字符串
使用三個引號或雙引號創(chuàng)建多行字符串
使用r創(chuàng)建原始raw字符串

2.2.3 布爾型-Boolean
使用bool表示布爾類型
布爾值只有true 和 false

2.2.4 列表-List
創(chuàng)建
- 創(chuàng)建List: var list = [1,2,3];

- 創(chuàng)建不可變的List:var list = const [1,2,3];

- 構(gòu)造創(chuàng)建:var list = new List();
常用操作
List.length
List.add()
List.insert()
List.remove()
List.clear()
List.indexOf()
List.lastIndexOf()
List.sort()
List.sublist()
List.shuffle()
List.asMap()
List.forEach()
var list = ["hello","dart"];
print(list.length);
list.add("java");
print(list);
list.remove("java");
print(list);
print(list.indexOf("dart"));
print(list.indexOf("java"));
list.insert(0, "2020");
print(list);
print(list.sublist(1));
print(list.reversed);
list.sort();
print(list);
list.clear();
print(list);
2
[hello, dart, java]
[hello, dart]
1
-1
[2020, hello, dart]
[hello, dart]
(dart, hello, 2020)
[2020, dart, hello]
[]
2.2.5 鍵值對-Map
- 創(chuàng)建
- 創(chuàng)建Map
var language = {"first":"Dart", "second" : "java"};
- 創(chuàng)建不可變Map
var language = const {"first":"Dart", "second" : "java"};
- 構(gòu)造創(chuàng)建
var language = new Map();
- 常用操作
1)Map.length
2)Map.isEmpty()、Map.isNotEmpty()
3)Map.Keys、 Map.values
4)Map.containsKey()、Map.containsValue()
5)Map.remove()
6)Map.forEach()
2.2.6 Runes、Symbols

3、運算符
3.1 算術(shù)運算符
加減乘除: +、-、*、/、~/、%
遞增遞減:++var、var++、--var、var--
3.2 關(guān)系運算符
運算符:==、!=、>、<、>=、<=
判斷內(nèi)容是否相同使用 ==
3.3 邏輯運算符
運算符:!、&&、||
針對布爾類型運算
3.4 賦值運算符
基礎(chǔ)運算符:=、??=
復合運算符:+=、-=、*=、/=、%=、~/=
3.5 條件表達式
三目運算符:condition?expr1 : expr2
?? 運算符:expr1 ?? expr2
4、控制語句
4.1 if語句
if 語句
if...else if 語句
if...else if ...else 語句
4.2 for語句
for 循環(huán)
for ... in循環(huán)
4.3 while語句
while 循環(huán)
do ... while循環(huán)
4.4 break 和 continue語句
終止循環(huán):break
跳出當前循環(huán):continue
4.5 switch...case語句
比較類型:num、String、編譯期常量
非空case必須有一個break
default 處理默認情況
continue跳轉(zhuǎn)標簽

5、方法
5.1 方法的定義
- 方法的定義與使用
返回類型 方法名 (參數(shù)1,參數(shù)2...){
方法體
return 返回值
}

方法的特性
方法也是對象,并且有具體類型Function
返回值類型、參數(shù)類型都可省略
箭頭語法: => expr 是 { return expr; }縮寫。只適用于一個表達式
方法都有返回值。如果沒有指定,默認 return null 最后一句
5.2 可選參數(shù)
可選命名參數(shù):{param1, param2, ...}
可選位置參數(shù):{param1,param2, ...}
如果存在具體參數(shù),可選參數(shù)聲明,必須在參數(shù)后面
5.3 默認參數(shù)值
使用 = 在可選參數(shù)指定默認值
默認值只能是編譯時常量
5.4 方法對象
方法可作為對象賦值給其它變量
方法可作為參數(shù)傳遞給其它方法
5.5 匿名方法
- 定義
(參數(shù)1. 參數(shù)2, ...) {
方法體
return 返回值
}
特性
可賦值給變量,通過變量進行調(diào)用
可在其它方法中直接調(diào)用或傳遞給其它方法
5.6 閉包
閉包是一個方法(對象)
閉包定義在其它方法內(nèi)部
閉包能夠訪問外部方法內(nèi)的局部變量,并持有其狀態(tài)
void main(){
var func = a();
func();
func();
func();
}
a(){
int count = 0;
//閉包
// printCount(){
// print(count++);
// }
// return printCount;
// 更多是使用匿名方式的閉包
return (){
print(count++);
};
}
6、Dart 面向?qū)ο缶幊?/h2>
6.1 類與對象
類與對象
使用關(guān)鍵字 class聲明一個類
使用關(guān)鍵字new 創(chuàng)建一個對象,new 可省略
所有對象都繼承于 Object類
void main(){
var person = new Person();
}
class Person{
int age;
String name;
}
-
屬性與方法
1)屬性默認會生成getter 和 setter方法
2)使用 final聲明的屬性只有 getter方法
3)屬性和方法通過 . 訪問
4)方法不能被重載
void main(){
var person = new Person();
person.name = "追夢小樂";
person.age = 20;
print(person.name);
print(person.age);
person.work();
print(person.address);
}
class Person{
int age;
String name;
final String address = "";
void work(){
print("姓名:$name 年齡:$age , is working.......");
}
}
-
類及成員的可見性
1)Dart 中的可見性以 library (庫)為單位
2)默認情況下,每一個 Dart 文件就是一個庫
3)使用 _ 表示庫的私有性
4)使用 import 導入庫
6.2 計算屬性
顧名思義,計算屬性的值是通過計算而來,本身不存儲值
計算屬性賦值,其實是通過計算轉(zhuǎn)換到其它實例變量
void main(){
var rect = new Rectangle();
rect.width = 10;
rect.height = 20;
print(rect.area);
rect.area = 200;
print(rect.width);
}
class Rectangle {
num width,height;
//計算屬性
// num get area {
// return width * height;
// }
//計算屬性簡寫模式
num get area => width * height;
set area(value){
width = value / 10;
}
}
6.3 構(gòu)造方法
-
默認構(gòu)造方法
1)如果沒有自定義構(gòu)造方法,則會有個默認構(gòu)造方法
void main(){
}
class Person{
int age;
String name;
final String gender = null;
Person(){
}
void work(){
print("working =============");
}
}
-
自定義構(gòu)造方法
1)如果存在自定義構(gòu)造方法,則默認構(gòu)造方法無效
void main(){
Person person = new Person(20, "追夢小樂", "女");
}
class Person{
int age;
String name;
final String gender;
//語法糖形式
Person(this.age,this.name,this.gender);
// 一般形式,雖說跟語法糖形式作用一樣,但是有個區(qū)別,就是final修飾的變量,在這里是不能被賦值的
// Person(int age,String name,String gender){
// this.age = age;
// this.name = name;
// this.gender = gender;
// }
void work(){
print("working ===============");
}
}
-
命名構(gòu)造方法
1)構(gòu)造方法不能重載
void main(){
Person person = new Person(20, "追夢小樂", "女");
new Person.withName("風行者", "男");
new Person.withAge(20, "男");
}
class Person{
int age;
String name;
final String gender;
//語法糖形式
Person(this.age,this.name,this.gender);
Person.withName(String name, this.gender){
this.name = name;
}
Person.withAge(int age, this.gender){
this.age = age;
}
void work(){
print("working ===============");
}
}
6.4 常量構(gòu)造方法
image.png
如果類是不可變狀態(tài),可以把對象定義為編譯時常量
使用 const 聲明
void main(){
const person = const Person(20, "追夢小樂", "女");
person.work();
}
class Person{
final int age;
final String name;
final String gender;
//語法糖形式
const Person(this.age,this.name,this.gender);
void work(){
print("working ===============");
}
}
6.5 工廠構(gòu)造方法
image.png
class Logger{
final String name;
static final Map<String,Logger> _cache = <String,Logger>{};
factory Logger(String name){
return Logger._internal("dart");
}
Logger._internal(this.name);
void log(String msg){
print(msg);
}
}
6.6 初始化列表
image.png
void main(){
var person = Person(20, "追夢小樂", "女");
person.work();
}
class Person{
int age;
String name;
final String gender;
//語法糖形式
Person(this.age,this.name,this.gender);
Person.withName(Map map) : gender = map["gender"]{
this.name = map["name"];
this.age = map["age"];
}
void work(){
print("working ===============");
}
}
6.7 靜態(tài)成員
image.png
void main(){
var page = new Page();
page.scrollUp();
Page.scrollDown();
}
class Page{
static const int maxPage = 10;
static int currentPage = 1;
static void scrollDown(){
currentPage = 1;
print("scrollDown======");
}
void scrollUp(){
currentPage++;
print("scrollUp======");
}
}
6.8 對象操作符
- 條件成員訪問 ?.
void main(){
Person person;
person ?.work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
- 類型轉(zhuǎn)換:as
void main(){
var person;
person = "";
person = new Person();
(person as Person).work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
- 是否指定類型 :is , is!
void main(){
var person;
person = "";
if(person is Person){
person.work();
}
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
- 級聯(lián)操作: ..
void main(){
Person person = new Person();
person..name = "追夢小樂"
..age = 20
..work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
6.9 對象call方法
image.png
void main(){
var person = new Person();
person.call("追夢小樂", 20);
}
class Person{
String name;
int age;
//返回值可以有,也可以為空,可以有參也可以無參
String call(String name,int age){
return "name is $name, age is $age";
}
}
類與對象
使用關(guān)鍵字 class聲明一個類
使用關(guān)鍵字new 創(chuàng)建一個對象,new 可省略
所有對象都繼承于 Object類
void main(){
var person = new Person();
}
class Person{
int age;
String name;
}
屬性與方法
1)屬性默認會生成getter 和 setter方法
2)使用 final聲明的屬性只有 getter方法
3)屬性和方法通過 . 訪問
4)方法不能被重載
void main(){
var person = new Person();
person.name = "追夢小樂";
person.age = 20;
print(person.name);
print(person.age);
person.work();
print(person.address);
}
class Person{
int age;
String name;
final String address = "";
void work(){
print("姓名:$name 年齡:$age , is working.......");
}
}
類及成員的可見性
1)Dart 中的可見性以 library (庫)為單位
2)默認情況下,每一個 Dart 文件就是一個庫
3)使用 _ 表示庫的私有性
4)使用 import 導入庫
顧名思義,計算屬性的值是通過計算而來,本身不存儲值
計算屬性賦值,其實是通過計算轉(zhuǎn)換到其它實例變量
void main(){
var rect = new Rectangle();
rect.width = 10;
rect.height = 20;
print(rect.area);
rect.area = 200;
print(rect.width);
}
class Rectangle {
num width,height;
//計算屬性
// num get area {
// return width * height;
// }
//計算屬性簡寫模式
num get area => width * height;
set area(value){
width = value / 10;
}
}
默認構(gòu)造方法
1)如果沒有自定義構(gòu)造方法,則會有個默認構(gòu)造方法
void main(){
}
class Person{
int age;
String name;
final String gender = null;
Person(){
}
void work(){
print("working =============");
}
}
自定義構(gòu)造方法
1)如果存在自定義構(gòu)造方法,則默認構(gòu)造方法無效
void main(){
Person person = new Person(20, "追夢小樂", "女");
}
class Person{
int age;
String name;
final String gender;
//語法糖形式
Person(this.age,this.name,this.gender);
// 一般形式,雖說跟語法糖形式作用一樣,但是有個區(qū)別,就是final修飾的變量,在這里是不能被賦值的
// Person(int age,String name,String gender){
// this.age = age;
// this.name = name;
// this.gender = gender;
// }
void work(){
print("working ===============");
}
}
命名構(gòu)造方法
1)構(gòu)造方法不能重載
void main(){
Person person = new Person(20, "追夢小樂", "女");
new Person.withName("風行者", "男");
new Person.withAge(20, "男");
}
class Person{
int age;
String name;
final String gender;
//語法糖形式
Person(this.age,this.name,this.gender);
Person.withName(String name, this.gender){
this.name = name;
}
Person.withAge(int age, this.gender){
this.age = age;
}
void work(){
print("working ===============");
}
}

如果類是不可變狀態(tài),可以把對象定義為編譯時常量
使用 const 聲明
void main(){
const person = const Person(20, "追夢小樂", "女");
person.work();
}
class Person{
final int age;
final String name;
final String gender;
//語法糖形式
const Person(this.age,this.name,this.gender);
void work(){
print("working ===============");
}
}

class Logger{
final String name;
static final Map<String,Logger> _cache = <String,Logger>{};
factory Logger(String name){
return Logger._internal("dart");
}
Logger._internal(this.name);
void log(String msg){
print(msg);
}
}

void main(){
var person = Person(20, "追夢小樂", "女");
person.work();
}
class Person{
int age;
String name;
final String gender;
//語法糖形式
Person(this.age,this.name,this.gender);
Person.withName(Map map) : gender = map["gender"]{
this.name = map["name"];
this.age = map["age"];
}
void work(){
print("working ===============");
}
}

void main(){
var page = new Page();
page.scrollUp();
Page.scrollDown();
}
class Page{
static const int maxPage = 10;
static int currentPage = 1;
static void scrollDown(){
currentPage = 1;
print("scrollDown======");
}
void scrollUp(){
currentPage++;
print("scrollUp======");
}
}
void main(){
Person person;
person ?.work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
void main(){
var person;
person = "";
person = new Person();
(person as Person).work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
void main(){
var person;
person = "";
if(person is Person){
person.work();
}
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
void main(){
Person person = new Person();
person..name = "追夢小樂"
..age = 20
..work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}

void main(){
var person = new Person();
person.call("追夢小樂", 20);
}
class Person{
String name;
int age;
//返回值可以有,也可以為空,可以有參也可以無參
String call(String name,int age){
return "name is $name, age is $age";
}
}
你是怎樣理解父類繼承,接口實現(xiàn)和混入的?我們應該在什么場景下使用它們?
1.一般來講,單繼承,多實現(xiàn),混入是多繼承
A.繼承是子類需要復用父類的方法實現(xiàn)
B.實現(xiàn)接口是復用接口的參數(shù),返回值,和方法名,但不復用方法的實現(xiàn),在Dart中實現(xiàn)抽象類 更像在java中實現(xiàn)用interface修飾的接口
C.混入是多繼承,當被混入的類有多個同名方法時,調(diào)用子類的該方法時,會調(diào)用with聲明的最后一個擁有該方法的類中的該方法,同時混入中的父類不能繼承
在父類繼承的場景中,父類子類之間的構(gòu)造函數(shù)執(zhí)行順序是怎樣的?如果父類有多個構(gòu)造函數(shù),子類也有多個構(gòu)造函數(shù),如何從代碼層面確保父類子類之間構(gòu)造函數(shù)的正確調(diào)用?
class Point {
num x, y;
Point() : this.make(0,0);
Point.left(x) : this.make(x,0);
Point.right(y) : this.make(0,y);
Point.make(this.x, this.y);
void printInfo() => print('($x,$y)');
}
class Vector extends Point{
num z = 0;
/*5個構(gòu)造函數(shù)
Vector
Vector.left;
Vector.middle
Vector.right
Vector.make
*/
@override
void printInfo() => print('($x,$y,$z)'); //覆寫了printInfo實現(xiàn)
}


