Flutter之旅:Dart語法掃尾-包訪問-泛型--異常-異步-mixin

但願在閱讀本文以前,你已經閱讀了:
Flutter之旅:Dart的基礎語法
Flutter之旅:從源碼賞析Dart面向對象編程


一、其餘經常使用符號與關鍵字

1.1:級聯操做符:..

那Paint對象的設置來看:安全

---->[情景1:曾經的寫法]----
var paint = Paint();
paint.strokeCap = StrokeCap.round;
paint.style = PaintingStyle.stroke; //畫線條
paint.color = Color(0xffBBC3C5); //畫筆顏色
paint.isAntiAlias = true; //抗鋸齒
paint.filterQuality =  FilterQuality.high; //抗鋸齒

---->[情景2:級聯的寫法]----
paint
  ..strokeCap = StrokeCap.round
  ..style = PaintingStyle.stroke //畫線條
  ..color = Color(0xffBBC3C5) //畫筆顏色
  ..isAntiAlias = true //抗鋸齒
  ..filterQuality = FilterQuality.high;
複製代碼

很簡潔,很高大上有木有,bash


1.2: 條件調用符:?.

---->[情景1:普通調用]----
void main() {
  var a = -5;
  print(a.abs());//5
}

---->[情景2:普通調用前置空,會崩掉]----
var a = 5;
a=null;
print(a.abs());//NoSuchMethodError: The method 'abs' was called on null.

---->[情景3:?.調用不會崩掉,只返回null]----
var a = 5;
a = null;
print(a?.abs()); //null
複製代碼

1.3:類型判斷關鍵字、isis!as

var b=10;
print(b is String);//false
print(b is num);//true
print(b is! double);//true

String c="12315";
print((c as Comparable<String>).compareTo("a"));//-1  強制類型轉換
print((c as num).abs());//類型轉換異常
// type 'String' is not a subtype of type 'num' in type cast
複製代碼

2.庫的使用和可見性

2.1:庫的基本使用
import 'dart:math';//導入math內置庫
import 'package:flutter/material.dart';//根據文件系統路徑到包
複製代碼

2.2:類庫中的命名衝突: as 關鍵字的使用

當sin函數處於連個包中,而且兩個包都被導入,該怎麼辦微信

---->[utils/color_utils.dart]----
sin(double d){
}

---->[main.dart:5]----
import 'package:toly/utils/color_utils.dart';
import 'dart:math';
void main() {
  sin(5);
}

---->[解決方案]----
import 'package:toly/utils/color_utils.dart' as myMath;
import 'dart:math';

void main() {
  myMath.sin(5);
}
複製代碼

2.3:控制顯隱部分導入

被隱藏的對象沒法被外界訪問異步

import 'package:toly/utils/color_utils.dart' show sin;//只顯示sin函數
import 'package:toly/utils/color_utils.dart' hide sin;//只隱藏sin函數
複製代碼

2.4:權限訪問控制

須要注意的是,Dart中沒有private,public,protected修飾符。 如何作到訪問權限控制,是個問題,默認是能夠被訪問的。async

---->[painter/person.dart]----
class Person{
    String name;
    int age;
    Person(this.name,this.age);
  
    say(){
    print("my name is $name and i am $age years old.");
  }
}

---->[main.dart]----
import 'package:toly/painter/person.dart';

void main() {
  var toly = Person("toly", 25);
  print(toly.age);//25
  toly.say();//my name is toly and i am 25 years old.
}
複製代碼

Dart中規定,名稱前加下劃線能夠限制外部的訪問,以下_age。
方法名,文件名也是如此,不想對外暴露,前面加下劃線便可編程語言

---->[painter/person.dart]----
class Person{
  String name;
  int _age;
  Person(this.name,this._age);

  say(){
    print("my name is $name and i am $_age years old.");
  }
}

---->[main.dart]----
void main() {
  var toly = Person("toly", 25);
  toly.say();//my name is toly and i am 25 years old.
  print(toly._age);//報錯
}
複製代碼

2.5:libraryexport關鍵字的使用

這裏拿animation來舉例子,使用時導包:import 'package:flutter/animation.dart';
在源碼中animation.dart只作了一個概括暴露的動做。ide

library animation;

export 'src/animation/animation.dart';
export 'src/animation/animation_controller.dart';
export 'src/animation/animations.dart';
export 'src/animation/curves.dart';
export 'src/animation/listener_helpers.dart';
export 'src/animation/tween.dart';
export 'src/animation/tween_sequence.dart';
複製代碼

3.泛型

Dart中的泛型和Java中很是類似,可讓類型變得安全,代碼更加優雅。函數

3.1:泛型的使用

拿List類來講,在類定義時類名List後加了,在使用時List就能夠加一個類型。這樣的好處在於當你試圖添加其餘類型的數據到該List對象中時,會報錯。這樣就是的類型變得安全。post

---->[sky_engine/lib/core/list.dart:54]----
abstract class List<E> implements EfficientLengthIterable<E> {

---->[main.dart]----
void main() {
  var languages=List<String>();//定義一個泛型爲String的列表
  var odd=List<int>();//定義一個泛型爲int的列表
}
複製代碼


3.2:List,Map,Set特殊的初始化

這並不算泛型特色,只是List,Map,Set快速初始化的寫法。
只不過看起來有些奇怪,這裏說一下,之後會常見這些寫法。

var languageList = <String>['Java', 'Dart', 'Kotlin'];
var markMap = <String,int>{'Java':100, 'Dart':80, 'Kotlin':60};
var languageSet = <String>{'Java', 'Dart','Kotlin'};
複製代碼

3.3:泛型的限定

和Java語法一致,使用 來限定泛型的類型區域
以下面DiagnosticableNode中的泛型限定

class DiagnosticableNode<T extends Diagnosticable> extends DiagnosticsNode
複製代碼

3.4:泛型方法

在Dart中,方法也是能夠支持泛型的,好比下面的方法:
當調用var e = foo<int>("hello");則會報錯,改成foo<String>便可。

T add<T>(T t) {
  return t;
}
複製代碼

4.異步操做簡介

關於異步,是一個挺大的話題,這裏簡單提一下,以後有詳細介紹。

4.1:異步在Dart中的必要性

Dart是一個單線程的編程語言,耗時操做會形成線程阻塞。
就至關於我在燒開水,水燒開以前都沒法進行其餘動做,這顯然是不合理的。
我徹底能夠在燒水的時候去掃地,等水開了再去處理,須要一個Future對象用於後續處理

class Water{
  double temperature;
  Water(this.temperature);
  Future<Water> heat() {
    temperature=100;
    return Future<Water> (()=>this);
  }
}

main(){
    print("打開燒水開關");
    Water(0).heat().then((water){
      print('水已經燒開,如今溫度:${water.temperature},開始沖水');
    });
    print("掃地");
}
複製代碼


4.2:asyncawait關鍵字的使用

async表示異步,await表示等待。注意在異步操做中返回的是Future對象
這個對象用於,後續的處理,好比水燒開後去沖水什麼的。

heat() async{
  var water = await Water(0).heat();
  print('水已經燒開,如今溫度:${water.temperature},開始沖水');
  return water;
}
複製代碼

能夠卡看出,打開燒水開關後,接着是掃地,水燒開後再衝水,這就是異步操做。
更多的用法將在後面文件資源的讀取時作詳細闡述。


5.異常處理

5.1:異常不處理的狀況

結果因爲FormatException異常,程序直接崩潰
這並非咱們想要的,直接崩潰會形成極差的用戶體驗。

void main() {
    print(str2Num("a"));//FormatException: a
}

num str2Num(String str){
   return num.parse(str);
}
複製代碼

5.2:異常捕捉

這個和Java也是相似的,使用try...catch...finally代碼塊
這樣異常會經過日誌打印而且程序不會崩潰退出。 其中finally代碼塊中的語句無論異常與否,都會被執行

num str2Num(String str){
  var result= 0;
  try {
   result= num.parse(str);
  } catch (e) {
    print('發生異常:$e');
  } finally {
    print('最終會被執行的代碼塊');
  }
  return result;
}
複製代碼

5.3:指定異常或多個異常捕捉

使用on關鍵字,能夠指定捕捉某一類異常。

num str2Num(String str){
  var result= 0;
  try {
    result= num.parse(str);
  } on FormatException catch (e) {
    print('發生Format異常:$e');
  } on IOException catch(e){
    print('發生IO異常:$e');
  } finally {
    print('最終會被執行的代碼塊');
  }
  return result;
}
複製代碼

6.Dart中的多繼承

知道Dart支持多繼承,我是挺驚訝的,多繼承的問題在於父類構造可能被循環調用

6.mixin的使用

6.1:子類和父類構造函數調用順序

經過下面的代碼能夠看出,是先調用父類的構造方法

class Living {
  Living(){
    print("Runner");
  }
}

class Person extends Living{
  Person(){
    print("Person");
  }
}

main(){
  Person toly = Person();
}

---->[打印結果]----
Runner
Person
複製代碼

6.2:mixin是什麼?

首先mixin是一個定義類的關鍵字。直譯出來是混入,混合的意思
Dart爲了支持多重繼承,引入了mixin關鍵字,它最大的特殊處在於:
mixin定義的類不能有構造方法,這樣能夠避免繼承多個類而產生的父類構造方法衝突

class Living {
  Living(){
    print("Runner");
  }
}

class Runner {

  run(){
    print("run");
  }
}

class Walker{
  walk(){
    print("run");
  }
}

class Person extends Living with Walker,Runner{
  Person(){
    print("Person");
  }
}

main(){
  Person toly = Person();
  toly.run();
  toly.walk();
}
複製代碼

使用方法很簡單,在with關鍵字後面將類名,這是該類就是mixin類
mixin就至關於將其餘類的能力混入到當前類,仍是挺厲害的。
惟一的限制就是mixin類沒法擁有構造函數,若是有構造方法會怎樣? 報錯唄。


6.3:關於mixin關鍵字

使用class關鍵字定義的類是能夠當作mixin類使用的,好比上面的。
另外使用mixin關鍵字也能夠來定義mixin類,如:

mixin Walker{
  walk(){
    print("run");
  }
}
複製代碼

惟一的區別在於,你是否肯定它是一個mixin類。
當你在mixin聲明的類中定義構造方法,會直接報錯。


6.4:關於混入的方法重名

取後混入的

class Runner {
  go(){
    print("Runner-go");
  }
}

mixin Walker{
  go(){
    print("Walker-go");
  }
}

class Person with Runner,Walker{
  Person(){
    print("Person");
  }
}

main(){
  Person toly = Person();
  toly.go();//Walker-go
}
複製代碼

本文到此接近尾聲了,若是想快速嚐鮮Flutter,《Flutter七日》會是你的必備佳品;若是想細細探究它,那就跟隨個人腳步,完成一次Flutter之旅。
另外本人有一個Flutter微信交流羣,歡迎小夥伴加入,共同探討Flutter的問題,本人微信號:zdl1994328,期待與你的交流與切磋。

相關文章
相關標籤/搜索