Dart學習筆記-基礎篇

聲明

本筆記是我自己在學習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中的常量使用finalconst關鍵字修飾,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一樣有publicprivateprotected這些權限修飾符。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. 對象操作符

  1. ? 條件運算符

    var persion
    persion?.getName() //加上 ? 表示如果persion爲null則不會getName方法,相當於非null判斷。
    
  2. as 類型轉換符(強轉)

  3. is 類型判斷(相當於Java中的instanceOf)

  4. .. 級聯操作(連綴)

    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則只需要複寫抽象方法即可。由此可以說明以下兩點:

  1. 一個類到底是接口還是抽象類還是普通類,得看子類使用的是extends繼承還是implements實現。
  2. 抽象類中可以有抽象方法,也可以有非抽象方法,什麼樣的方法是抽象方法?沒有方法體的方法就是抽象方法。

注意,Dart與Java一樣,只可以多實現不可以多繼承。

3. mixins混合類

混合類其實是一個類似多繼承的這麼一個功能。爲什麼說類似多繼承?因爲從代碼上看,它確實很像多繼承。但使用mixins還有以下幾個條件:

  1. 做爲mixins的類只能繼承自Object,不能繼承其他類。
  2. 做爲mixins的類不能有構造函數。
  3. 一個類可以mixins多個mixins類。
  4. 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包管理系統中的庫。

三方庫的使用方法有以下幾步:

  1. 需要在自己的項目的根目錄中創建一個pubspec.yaml文件。

  2. 在pubspec.yaml文件中配置三方庫的名稱、描述、依賴等信息。

  3. 運行 pub get 命令將三方庫下載到本地。

  4. 在項目中要使用的.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);
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章