Dart 基本語法及使用 dart 一. dart 環境 二. 變量 三. 數據類型 四. 函數 五. 運算符 六. 類和對象 七. 枚舉類型 八. 泛型 九. 庫的使用

碎語,有android、iOS、前端、小程序、RN基礎,所以,以下記錄僅爲個人理解記錄,沒必要的就忽略的

dart

一. dart 環境

需求:演練dart語法,直接運行.dart代碼。。

$ dart xxx.dart

需要有dart環境支持

1 flutter中帶的有sdk

安裝flutter的時候,把dart的環境變量配置上即可

2 專門下載dart的sdk

https://dart.cn/get-dart

按文檔安裝dart sdk

1.1. vscode 演練dart

code runner 插件。

使用:右鍵-運行

二. 變量

跟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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章