Flutter之旅:Dart语法扫尾-包访问-泛型--异常-异步-mixin

希望在阅读本文之前,你已经阅读了:
Flutter之旅:Dart的基础语法
Flutter之旅:从源码赏析Dart面向对象


1、其他常用符号与关键字

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;

很简洁,很高大上有木有,


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修饰符。
如何做到访问权限控制,是个问题,默认是可以被访问的。

---->[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只做了一个归纳暴露的动作。

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后加了<E>,在使用时List就可以加一个类型。这样的好处在于当你试图添加其他类型的数据到该List对象中时,会报错。这样就是的类型变得安全。

---->[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的列表
}
image

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语法一致,使用<T extends B> 来限定泛型的类型区域
如下面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> changeTemperature(double t) {
    for(var i=0.0;i<=t;i+=0.01){//模拟烧水过程(耗时操作)
      temperature=i;
    }
    return Future<Water> (()=>this);
  }
}

4.2:asyncawait关键字的使用

async表示异步,await表示等待。注意在异步操作中返回的是Future<XXX>对象
这个对象用于,后续的处理,比如水烧开后去冲水什么的。

Future<Water> heat(Water water) async{//异步烧水
  return await water.changeTemperature(100);//返回烧开的水的Future
}

main(){
  print("打开烧水开关");
  heat(Water(0)).then((result){
    print('水已经烧开,现在温度:${result.temperature},开始冲水');
  });
  print("扫地");
}
image

可以卡看出,打开烧水开关后,接着是扫地,水烧开后再冲水,这就是异步操作。
更多的用法将在后面文件资源的读取时做详细阐述。


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类无法拥有构造函数,如果有构造方法会怎样? 报错呗。

image

6.3:关于mixin关键字

使用class关键字定义的类是可以当做mixin类使用的,比如上面的。
另外使用mixin关键字也可以来定义mixin类,如:

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

唯一的区别在于,你是否确定它是一个mixin类。
当你在mixin声明的类中定义构造方法,会直接报错。

image

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,期待与你的交流与切磋。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341

推荐阅读更多精彩内容