2、flutter--Dart

  一、Dart语言简介

  百度(玄语):

    Dart是谷歌开发的计算机编程语言,后来被Ecma (ECMA-408)认定为标准 [1]  。它被用于web、服务器、移动应用 [2]  和物联网等领域的开发。它是宽松开源许可证(修改的BSD证书)下的开源软件。
    Dart是面向对象的、类定义的、单继承的语言。它的语法类似C语言,可以转译为JavaScript,支持接口(interfaces)、混入(mixins)、抽象类(abstract classes)、具体化泛型(reified generics)、可选类型(optional typing)和sound type system
  白话:
    Dart 在设计时应该是同时借鉴了 Java 和 JavaScript,同时又引入了一些现代编程语言的特性。
    Dart 在静态语法方面和 Java 非常相似。如①类型定义、函数声明、泛型等,而②在动态特性方面又和 JavaScript 很像,如函数式特性、异步支持等。除了融合 Java 和 JavaScript 语言之所长之外,具有表现力的语法,如可选命名参数、..(级联运算符)和?.(条件成员访问运算符)以及??(判空赋值运算符)。在 Dart 中其实看到的不仅有 Java 和 JavaScript 的影子,它还具有其它编程语言中的身影,如命名参数在 Objective-C 和 Swift 中早就很普遍。

二、变量声明

1、var

  1、类似于 JavaScript 中的var

  2、不同是 Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变

2、dynamic 和 Object

  1、Object 是 Dart 所有对象的根基类,所以任何类型的数据都可以赋值给Object声明的对象

  2、dynamicObject声明的变量都可以赋值任意对象,且后期可以改变赋值的类型

  3、dynamicObject不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错

 

3、final和const

  1、从未打算更改一个变量,那么使用 final 或 const

  2、const 变量是一个编译时常量(编译时直接替换为常量值),final变量在第一次使用时被初始化。被final或者const修饰的变量,变量类型可以省略

//可以省略String这个类型声明
final str = "hi world";
//final String str = "hi world"; 
const str1 = "hi world";
//const String str1 = "hi world";

4、空安全(null-safety)

  1、Dart 中一切都是对象,这意味着如果我们定义一个数字,在初始化它之前如果我们使用了它,假如没有某种检查机制,则不会报错,如:

test() {
  int i; .//未初始化
  print(i*8);
}

  2、在 Dart 引入空安全之前,上面代码在执行前不会报错,但会触发一个运行时错误,原因是 i 的值为 null 。但现在有了空安全,则定义变量时我们可以指定变量是可空还是不可空

int i = 8; //默认为不可空,必须在定义时初始化。
int? j; //  定义为可空类型,对于可空变量,我们在使用前必须判空。

// 如果我们预期变量不能为空,但在定义时不能确定其初始值,则可以加上late关键字,
// 表示会稍后初始化,但是在正式使用它之前必须得保证初始化过了,否则会报错
late int k;
k=9;

  3、如果一个变量我们定义为可空类型,在某些情况下即使我们给它赋值过了,但是预处理器仍然有可能识别不出,这时我们就要显式(通过在变量后面加一个”!“符号)告诉预处理器它已经不是null了

三、函数

1、函数声明:如果没有显式声明返回值类型时会默认当做dynamic处理,注意,函数返回值没有类型

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}



typedef bool CALLBACK();

//不指定返回类型,此时默认为dynamic,不是bool
isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

void test(CALLBACK cb){
   print(cb()); 
}
//报错,isNoble不是bool类型
test(isNoble); 

2、对于只包含一个表达式的函数,可以使用简写语法

bool isNoble (int atomicNumber)=> true ;  

3、函数作为变量

var say = (str){
  print(str);
};
say("hi world");

4、函数作为参数传递

void execute(var callback) {
    callback();
}
execute(() => print("xxx"))

5、可选的位置参数

//包装一组函数参数,用[]标记为可选的位置参数,并放在参数列表的最后面:
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

//下面是一个不带可选参数调用这个函数的例子:
say('Bob', 'Howdy'); //结果是: Bob says Howdy


//下面是用第三个参数调用这个函数的例子:
say('Bob', 'Howdy', 'smoke signal'); //结果是:Bob says Howdy with a smoke signal

6、可选的命名参数

定义函数时,使用{param1, param2, …},放在参数列表的最后面,用于指定命名参数。例如:
//设置[bold]和[hidden]标志
void enableFlags({bool bold, bool hidden}) {
    // ... 
}

调用函数时,可以使用指定命名参数。例如:paramName: value
enableFlags(bold: true, hidden: false);

四、mixin

Dart 是不支持多继承的,但是它支持 mixin,简单来讲 mixin 可以 “组合” 多个类,我们通过一个例子来理解。

定义一个 Person 类,实现吃饭、说话、走路和写代码功能,同时定义一个 Dog 类,实现吃饭、和走路功能:我们定义了几个 mixin,然后通过 with 关键字将它们组合成不同的类。有一点需要注意:如果多个mixin 中有同名方法,with 时,会默认使用最后面的 mixin 的,mixin 方法中可以通过 super 关键字调用之前 mixin 或类中的方法。

class Person {
  say() {
    print('say');
  }
}

mixin Eat {
  eat() {
    print('eat');
  }
}

mixin Walk {
  walk() {
    print('walk');
  }
}

mixin Code {
  code() {
    print('key');
  }
}

class Dog with Eat, Walk{}
class Man extends Person with Eat, Walk, Code{}

五、异步支持

Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数:它们只会在设置好一些耗时操作之后返回

asyncawait关键词支持了异步编程,允许写出和同步代码很像的异步代码

1、Future

Future与JavaScript中的Promise非常相似,表示一个异步操作的最终完成(或失败)及其结果值的表示。简单来说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个Future只会对应一个结果,要么成功,要么失败。

由于本身功能较多,这里我们只介绍其常用的API及特性。还有,请记住,Future

 其他:待补充

六、Stream

Stream 也是用于接收异步事件数据,和 Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。举个例子:

Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});

输出:

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3

 

七、 Dart和Java及JavaScript对比

1、Dart vs Java

客观的来讲,Dart 在语法层面确实比 Java 更有表现力;在 VM 层面,Dart VM 在内存回收和吞吐量都进行了反复的优化,但具体的性能对比,笔者没有找到相关测试数据,但在笔者看来,只要 Dart 语言能流行,VM 的性能就不用担心,毕竟 Google 在 Go(没用VM但有GC)、JavaScript(v8)、Dalvik( Android 上的 Java VM )上已经有了很多技术积淀。值得注意的是 Dart 在 Flutter 中已经可以将 GC 做到 10ms 以内,所以 Dart 和 Java 相比,决胜因素并不会是在性能方面。而在语法层面,Dart 要比 Java 更有表现力,最重要的是 Dart 对函数式编程支持要远强于 Java(目前只停留在 Lambda 表达式),而 Dart 目前真正的不足是生态,但笔者相信,随着 Flutter 的逐渐火热,会回过头来反推 Dart 生态加速发展,对于 Dart 来说,现在需要的是时间。

2、Dart vs JavaScript

JavaScript 的弱类型一直被抓短,所以 TypeScript 甚至是 Facebook 的 Flow 才有市场。就笔者使用过的脚本语言中(笔者曾使用过 Python、PHP),JavaScript 无疑是动态化支持最好的脚本语言,比如在 JavaScript 中,可以给任何对象在任何时候动态扩展属性,对于精通 JavaScript 的高手来说,这无疑是一把利剑。但是,任何事物都有两面性,JavaScript 强大的动态化特性也是把双刃剑,你可经常听到另一个声音,认为 JavaScript 的这种动态性糟糕透了,太过灵活反而导致代码很难预期,无法限制不被期望的修改。毕竟有些人总是对自己或别人写的代码不放心,他们希望能够让代码变得可控,并期望有一套静态类型检查系统来帮助自己减少错误。正因如此,在 Flutter中,Dart 几乎放弃了脚本语言动态化的特性,如不支持反射、也不支持动态创建函数等。并且 Dart 从 2.0 开始强制开启了类型检查(Strong Mode),原先的检查模式(checked mode)和可选类型(optional type)将淡出,所以在类型安全这个层面来说,Dart 和 TypeScript、CoffeeScript 是差不多的,所以单从动态性来看,Dart 并不具备什么明显优势,但综合起来看,Dart 既能进行服务端脚本、APP 开发、Web 开发,这就有优势了!

posted @ 2021-11-29 18:04  夜凉初透陌汐  阅读(729)  评论(0编辑  收藏  举报