碎語,有android、iOS、前端、小程序、RN基礎,所以,以下記錄僅爲個人理解記錄,沒必要的就忽略的
dart
一. dart 環境
需求:演練dart語法,直接運行.dart代碼。。
$ dart xxx.dart
需要有dart環境支持
1 flutter中帶的有sdk
安裝flutter的時候,把dart的環境變量配置上即可
2 專門下載dart的sdk
按文檔安裝dart sdk
1.1. vscode 演練dart
code runner 插件。
使用:右鍵-運行
- 也可以使用網頁工具練習dart代碼:https://dartpad.dartlang.org
二. 變量
跟ios像,優點是有類型推到,比如:var
dynamic 不建議使用
公私有性
dart中沒有public,private,protected等,,
- 對象中,變量_field加下劃線,就表示私有了。。只能當前文件訪問
特殊 const
雖然js,oc裏有,但是用法不一樣,這個dart的還挺有意思
final a = const Person();
final b = const Person();
print(identical(a, b)); // true
final m = Person();
final n = Person();
print(identical(m, n)); // false
late 關鍵字
https://blog.csdn.net/weixin_44239910/article/details/118196797
- 聲明變量的時候,需要初始化,使用late關鍵字:顯式聲明一個非空的變量,但不初始化。。這樣有風險
- 延遲初始化變量:有點像懶加載,用到的時候纔會初始化
late String temperature = _readThermometer();
dynamic
任意類型,是一個明確類型,比如
Map<String, dynamic> map
//這樣是可以的
String str = map[''];
this.height = double.parse(map['height'].toString());
- 如果map中value類型是Object,那麼就不能直接那樣取,,dart沒有 (String)obj這樣的類型強轉,,所以,可以使用其他方法
- 使用dynamic,表示任意類型
- 或者使用map['key'] as String 這種方式,,
- int.parse(string)
- int.toString()
注意:使用as語法,你要提前知道類型,如果類型不匹配,就報錯。
所以,所使用的方法的類型匹配的前提下,可以轉換類型的。。
三. 數據類型
布爾
注意: Dart中不能判斷非0即真, 或者非空即真
Dart的類型安全性意味着您不能使用if(非booleanvalue)或assert(非booleanvalue)之類的代碼。
字符串
三引號,可以換行的字符串。打印結果也是換行的
var str = """
ab
bc
cd
""";
字符串拼接:對象可以省略{},表達式則不能省略{}
如:print('my name is ${name}, age is $age, height is ${xiaoming.height}');
集合類型
list,set,map 普通,沒啥特別的
四. 函數
基本定義:
返回值 函數的名稱(參數列表) {
函數體
return 返回值
}
dart中沒有關鍵字表示公私有性,使用'_'下劃線標記私有。如:_method() 就是私有的。。
dart中沒有函數重載,也就是不允許有同名函數(同類中)
4.1. 函數的可選參數
位置可選參數
注意形參:要有默認值
void method1(String name, [int age = 1, int? h]) {
print('name is $name, age is $age, h is $h');
}
調用:
method1('name', 2);
結果:
name is name, age is 2, h is null
命名可選參數
void method2(String name, {int? age, String? add}) {
print('name is $name, age is $age, h is $add');
}
調用:
method1('name', 33);
結果:
name is name, age is 33, h is null
注意:
- 只有可選參數能有默認值
4.2. 函數是一等公民
void method3(Function func) {
}
匿名函數
method3(() {
});
箭頭函數
method3(() => print("xxx"));
只有一行代碼的時候,可以使用箭頭函數
注意:其實不太對,實踐:
method3(() => {
print("xxx"),
print('object')
});
這樣是可以的,只是要注意箭頭函數體內不能有分號
函數形參
可以使用功能typedefine提出來函數定義
五. 運算符
??=
var name = null;
name ??= 'jjjj';
變量沒有值,才執行??=
??
var s = null;
var ss = s ?? 'ssss';
?? 前沒有值則用??後面的值
5.1. 級聯運算符
final p2 = Person()
..name = "why"
..run()
..eat()
..swim();
特定語法,記住就行
六. 類和對象
默認繼承 Object..跟 android 一樣
6.1. 構造方法
6.1.1. 命名構造函數
class Person {
String name = '';
int age = 0;
double height = 1.8;
Person(this.name, this.age);
Person.externalWithHieght(this.name, this.age, this.height);
Person.fromMap(Map<String, dynamic> map) {
this.name = map['name'];
this.age = map['age'];
this.height = map['height'];
}
}
調用:
Person person = Person.externalWithHieght('name', 19, 1.9);
person = Person.fromMap({'name':'leixing', 'age':19, 'height':1.99});
print(person.toString());
- 由於dart中函數是不能重載的,也就是不能有同名函數,所以,多構造函數可以通過.實現,如上。。
- 打印對象:結果是Instance of 'Person'。。所以,類中需要重寫toString方法的。這個java一樣
6.1.2. 類的初始化列表
class Person1 {
late final String name;
final int age;
//other field 其他參數可選列表,用逗號隔開
Person1(this.name, {int? age, other field}) : this.age = age ?? 10, other field {
}
//這裏也可以實現外部傳值給final的age,,但是注意:requered表示外部初始Person1的時候必須傳age,就失去了可選參數的意義
Person1(this.name, {required this.age}) {
}
//也可以這樣,,但是注意:侷限性是命名可選參數裏不能寫表達式,比如三目運算符
Person1(this.name, {this.age = 10}) {
}
Person1.withName(this.name) : age = 2 {
}
}
針對age這種變量,如果在聲明的時候指定初始值,那麼外部就沒辦法再初始化的時候後指定值了。。
初始化列表: 可以使用這種技術,初始化列表就支持在運行的時候賦值final變量
解析:{int? age}
是命名可選參數,後面的:xxx
是初始化列表,這裏是可以賦值的。。這樣就解決了在方法體中對final變量賦值的動態需求
6.1.3. 重定向構造方法
class Person2 {
String name;
final int age;
//重定向構造方法,用冒號,後面用this,表示前面已經初始化過了,後面可以使用this對象進行參數擴展
//注意:重定向構造方法不能傳可選參數。這是語法規定。可選參數只能供外部調用。內部調用只能調用最全的構造方法:_withNameAndAge
//注意:形參要單純,不能進行初始化,比如下面:只能 String name,而不能this.name。也就是說,不能先初始化了一部分,又去重定向。。這一點倒是沒有java靈活
//The redirecting constructor can't have a field initializer.
//重定向構造方法,很像開發java的時候,那種入參較多,構造方法較多的情況。。
Person2(String name): this._internal(name);
Person2._internal(this.name, {int?age}): this.age = age ?? 1;
Person2._optionalAge(this.name, {this.age = 2});
Person2.withName(String name): this._withNameAndAge(name, 1);
Person2._withNameAndAge(this.name, this.age);
@override
String toString() {
// TODO: implement toString
return 'age is $age';
}
}
6.1.4. 常量構造方法
main(List<String> args) {
var p1 = const Person('why');
var p2 = const Person('why');
print(identical(p1, p2)); // true
}
class Person {
final String name;
const Person(this.name);
}
class Person3 {
final String name;
final int age;
//注意:加了const,變量就必須是final的
const Person3(String name): this._withAge(name, 1);
const Person3._withAge(this.name, this.age);
}
const person3 = Person3._withAge('name', 222);
const person31 = Person3._withAge('name', 222);
print(identical(person3, person31));// true
常量構造函數,語法就是這麼規定的,變量前加final,構造函數前加const
6.1.5. 工廠構造方法
main(List<String> args) {
var p1 = Person('why');
var p2 = Person('why');
print(identical(p1, p2)); // true
}
class Person {
String name;
static final Map<String, Person> _cache = <String, Person>{};
factory Person(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final p = Person._internal(name);
_cache[name] = p;
return p;
}
}
Person._internal(this.name);
}
- 工廠構造函數最大的特點:可以手動返回一個對象。。必須用factory 修飾構造函數
6.1.6. setter和getter
class Person {
String name = '';
set setName(String name) {
this.name = name;
}
set setName1(String name) => this.name = name;
String get getName {
return name;
}
//this寫不寫都可以,反正就是一個name變量,沒有局部變量
String get getName1 => this.name;
}
6.2. 類的繼承
- 關鍵字 extend
- 單繼承
- 跟重定向不同,繼承,構造函數可以先初始化一部分,然後調用super中對應參數的構造函數
Person(String name, int age) : name=name, super(age);
6.3. 抽象類
- 關鍵字,和規則 跟其他語言一樣
- 特殊點:
抽象類如何實現實例化
- 提供工廠構造方法
- erternal 關鍵字 可以將方法的聲明和實現進行分離,@patch註解 進行方法的實現,可以讓實際實例化代碼實現不同的方法。跟多態差不多
6.4. 隱式接口
Dart中的接口比較特殊, 沒有一個專門的關鍵字來聲明接口.
默認情況下,定義的每個類都相當於默認也聲明瞭一個接口,可以由其他的類來實現(因爲Dart不支持多繼承)
- 關鍵字:implements
6.5. Mixin混入
在通過implements實現某個類時,類中所有的方法都必須被重新實現(無論這個類原來是否已經實現過該方法)。
但是某些情況下,一個類可能希望直接複用之前類的原有實現方案,怎麼做呢?
使用繼承嗎?但是Dart只支持單繼承,那麼意味着你只能複用一個類的實現。
Dart提供了另外一種方案: Mixin混入的方式除了可以通過class定義類之外,也可以通過mixin關鍵字來定義一個類。
只是通過mixin定義的類用於被其他類混入使用,通過with關鍵字來進行混入。如果方法重名:自己 > 混入 > 繼承 > 接口
6.6. 類成員和方法
跟普通語言一致
七. 枚舉類型
可讀性
類型安全
八. 泛型
同java
九. 庫的使用
默認:一個dart文件就是一個庫文件
使用系統的庫
核心庫不需要導入:'dart:core'
非核心庫,用到的會自動導入:'dart:math'
封裝庫
- as關鍵字給庫起別名
- 默認是導入庫的所有內容:
- show:導入指定的內容
- hide:隱藏某內容,導入除之之外的所有內容
- 導入多個庫的時候,使用export,也就是把需要導入的庫放到一個dart文件中統一導入
dart_util.dart:
export 'math_util.dart'
export 'date_util.dart'
引用:
import 'dart_util.dart'
- 通過'_'來區分公有和私有。變量和函數 都適用
三方庫
1、創建 pubspec.yaml文件 //這個文件像podfile和gradle
2、依賴庫
name: 一般是你工程名
description: A new Flutter project.
dependencies:
http: 版本 // 去三方庫網站 - 庫 - installing - dependencies
3、加載依賴
cd到yaml文件路徑:pub get
新生成的三個文件不用管:oubspec.lock .dart_tool .packages
4、引用庫
import 'package:xxx'
三方庫網站 - 庫 - readme - using