当前位置: 首页 > 工具软件 > Dart Editor > 使用案例 >

Android Flutter:Dart语言(语法篇)

洪开诚
2023-12-01

一、语言特性

  • 基本类型:bool,int,double。没有 byte、char 和 float
  • final和java中一样,赋值不可再改变。const 表示一个编译时常量,在程序编译的时候它的值就确定了
  • Dart 里所有的东西都是对象,包括 int、函数、null,所有对象继承制Object
  • Dart 是动态类型语言, 尽量给变量定义一个类型,会更安全,没有显示定义类型的变量在 debug 模式下会类型会是 dynamic(动态的),未初始化的变量的初始值为null(包括数字)
  • Dart 提供了顶级函数(如:main())
  • Dart 没有 public、private、protected 关键字,变量名以"_"开头意味着对它的 lib 是私有的
  • Dart 中的类和接口是统一的,类即接口,类/接口可以继承也可以实现。同时支持基于mixin的继承方式,一定程度上可以多重继承。

二、组成

编程语言并不是孤立存在的,Dart也是这样,他由语言规范、虚拟机、类库和工具等组成:

  • SDK:SDK 包含 Dart VM、dart2js、Pub、库和工具。
  • Dartium:内嵌 Dart VM 的 Chromium ,可以在浏览器中直接执行 dart 代码。
  • Dart2js:将 Dart 代码编译为 JavaScript 的工具。
  • Dart Editor:基于 Eclipse 的全功能 IDE,并包含以上所有工具。支持代码补全、代码导航、快速修正、重构、调试等功能。

三、语法(与java差异)

1、检测两个 String 的内容是否一样事,我们使用 == 进行比较;如果要测试两个对象是否是同一个对象(indentity test),使用 identical 函数

2、Dart 提供了 for-in 循环,forEach循环

var list = ['apples', 'bananas', 'oranges'];
for (var e in list) {
  print(e);
}

list.forEach((item) {
   print('${list.indexOf(item)}: $item');
});

如果函数只包含一条语句,可以使用箭头符号=>来缩短它

list.forEach((item) => print('${list.indexOf(item)}: $item'));

3、类型判断关键字(顺带转换) is,类型的强制转换关键字 as

dynamic obj = <String, int>{};
if (obj is Map<String, int>) {  
// 进过类型判断后,Dart 知道 obj 是一个 Map,所以不用再强制转换 obj 的类型 
obj['foo'] = 42;
}

// 虽然as可以进行类型的强制转换,但为了更安全的转换,更推荐使用 is
var map = obj as Map<String, int>

4、可以使用单引号或双引号来创建一个字符串。嵌套时,可以单引号嵌套双引号,或者双引号嵌套单引号。使用表达式时需要${表达式} 

String hello= 'hello world';
String words = '"what he said" - ${hello}';
print(words);
//输出 "what he said" - hello world

5、在Dart中,数组是List对象,可以直接打印,在java中需遍历。

 //创建一个int类型的list
 List list = [10, 7, 23];
 // 输出[10, 7, 23]
 print(list);
 
 // 使用List的构造函数,也可以添加int参数,表示List固定长度,不能进行添加 删除操作
 var fruits = new List();
 
 // 添加元素
 fruits.add('apples');
 
 // 添加多个元素
 fruits.addAll(['oranges', 'bananas']);
 
 List subFruits = ['apples', 'oranges', 'banans'];
 // 添加多个元素
 fruits.addAll(subFruits);
 
 // 输出: [apples, oranges, bananas, apples, oranges, banans]
 print(fruits);
 
 // 获取List的长度
 print(fruits.length);
 
 // 获取第一个元素
 print(fruits.first);
 
 // 获取元素最后一个元素
 print(fruits.last);
 
 // 利用索引获取元素
 print(fruits[0]);
 
 // 查找某个元素的索引号
 print(fruits.indexOf('apples'));
 
 // 删除指定位置的元素,返回删除的元素
 print(fruits.removeAt(0));

 // 删除指定元素,成功返回true,失败返回false
 // 如果集合里面有多个“apples”, 只会删除集合中第一个改元素
 fruits.remove('apples');

 // 删除最后一个元素,返回删除的元素
 fruits.removeLast();

 // 删除指定范围(索引)元素,含头不含尾
 fruits.removeRange(start,end);

 // 删除指定条件的元素(这里是元素长度大于6)
 fruits.removeWhere((item) => item.length >6);

 // 删除所有的元素
 fruits.clear();

6、Map

//声明方式一:
Map companys = {'Alibaba': '阿里巴巴', 'Tencent': '腾讯', 'baidu': '百度'};
//声明方式二:
Map companys = new Map();
companys['Alibaba'] = '阿里巴巴';

// 指定键值对的参数类型
var aMap = new Map<int, String>();

// Map的赋值,中括号中是Key,这里可不是数组
aMap[1] = '小米';
//map里面value可以为空字符串,也可以为null
aMap[2] = '';

// 检索Map是否含有某Key
assert(aMap.containsKey(1));
//删除某个键值对
aMap.remove(1);

7、函数

Dart 中支持可选参数、也可以默认参数。如果是

void main() {  
    print(foo(2));  
    print(foo(1, 2));
}

int foo(int x, [int y]) {  
    // 是的,int 也可以是 null  
    if (y != null) {   
         return x + y;  
    }  
        return x;
}
//默认参数也是支持的
int foo(int x, [int y = 0]) {
  return x + y;
}

可以使用具名参数,具名参数是必须的时候,使用注解 @required

void main() {
    print(foo(x: 1, y: 2));  
    // 具名参数的顺序可以是任意的  
    print(foo(y: 3, x: 4));  
    // 所有的具名参数都是可选的,这个调用是合法的,但它会导致 foo() 在运行时抛异常  
    print(foo());
}

int foo({ @required int x, int y}) {  
    return x + y;
}

Dart 不支持函数的重载。

8、Dart 可以抛出任意类型的对象,甚至可以通过 rethrow 再抛出异常

throw Exception('here is an error message');  
throw 'Out of Control!';
try { 

} on FormatException catch (e) {  // 捕获特定类型的异常

} on Exception {  // 捕获特定类型的异常,但不需要这个对象

} catch (e) {  // 捕获所有异常

} finally {  

}
void test() {
    try {
      print('1');
    } catch (e) {
      print('2');
      rethrow;// 如果不重新抛出异常,main函数中的catch语句执行不到
    }
 }

 void main() {
    try {
      test();
    } catch (e) {
      print('3');
    }
 }

9、级联符号 ..  允许在同一个对象上进行一系列操作

querySelector('#confirm') 
    ..text = 'Confirm' 
    ..classes.add('important')
    ..onClick.listen((e) => window.alert('Confirmed!'));


 //上面的写法相当于下面,需要注意的是级联的前提是返回值部委void
 var button = querySelector('#confirm');
 button.text = 'Confirm';
 button.classes.add('important');
 button.onClick.listen((e) => window.alert('Confirmed!'));

10、使用new语句来构造一个类,构造函数的名字可能是ClassName,也可以是ClassName.identifier

var jsonData = JSON.decode('{"x":1, "y":2}');

// Create a Point using Point().
var p1 = new Point(2, 2);

// Create a Point using Point.fromJson().
var p2 = new Point.fromJson(jsonData);

11、使用   ?. 来确认前操作数不为空, 常用来替代. , 避免左边操作数为null引发异常

// If p is non-null, set its y value to 4.
p?.y = 4;

12、类的初始化

//方式一
class point {
  int x;
  int y;

  point(this.x, this.y);
}

//方式二:初始化列表(initializer list)的方式
class Point {  
  int x;  
  int y; 
  // 由于是在 initializer list 中,Dart 知道第一个 x 是 this.x,  
  // 第二个 x 是构造函数的参数  
  Point(int x, int y) : x = x, y = y {    
  // ...  
 }
}

 13、继承

class Point2D {  
  int x;  
  int y;  
  Point2D(this.x, this.y);
}

class Point3D extends Point2D {  
  int z;  
  // 父类的构造函数只能在 initializer list 里调用 
  Point3D(int x, int y, int z): z = z, super(x, y) { 
  }
}

注意一下初始化顺序:

  1. 先执行子类 initializer list,但只初始化自己的成员变量
  2. 初始化父类的成员变量
  3. 执行父类构造函数的函数体
  4. 执行之类构造函数的函数体

基于这个初始化顺序,推荐是把 super() 放在 initializer list 的最后。此外,在 initializer list 里不能访问 this(也就是说,只能调用静态方法)

使用 mixins 多继承,在 with 关键字后面跟一个或多个 mixin 的名字。

class dove extends Birds with Animal {
      // ...
 }

mixins的多重继承是一定程度的,被mixin的类不声明任何构造函数,不调用 super  

abstract class Animal{
    bool canFly = false;
    bool canCry = false;

   void entertainMe() {
     if (canFly ) {

     } else if (canCry ) {

     } else {

     }
   }
}

14、异步和线程

Dart 是单线程的,主线程由一个事件循环来执行(类似 Android 的主线程)。对于异步代码,我们通过 Future 来获取结果

void foo1() {  
  var file = File('path-to-your-file');  
  file.exists()      
    .then((exists) => print('file ${exists ? 'exists' : 'not exists'}'))      
    .catchError((e) => print(e));
  print('bar: after file.exists() returned');
}

Dart 2 提供了 async 函数,用来简化这种编程范式。下面这段代码的效果跟上面是一样的,但有区别:foo1 函数里面,file.exists() 执行完后,会马上执行下面的语句;而 foo2 则会等待结果,然后才继续执行。

void foo2() async {  
  var file = File('path-to-your-file');  
  try {    
    var exists = await file.exists();    
    print('file ${exists ? 'exists' : 'not exists'}');  
    print('bar: after file.exists() returned');
  } catch (e) {    
    print(e);  
  }
}

 

感谢:

https://www.jianshu.com/p/9e5f4c81cc7d

https://juejin.im/post/5bcc8527f265da0aff17729a#heading-11

 类似资料: