第 1-2 课:Dart 语言基础

Flutter:从入门到实践 专栏收录该内容
41 篇文章 4 订阅 ¥99.00 ¥49.90

学习一门编程语言,首页要了解它的历史和特点。Dart 是 Google 公司推出的编程语言,于 2011 年就已经亮相了。Dart 也是一门面向对象的语言,语法和 Java、C、JavaScript 很像。所以会 Java 语言,学习 Dart 一般会快一些。

Dart 里所有的类都可以看成是对象,是单继承,动态类语言。可以进行多平台开发,我们的主角 Flutter 就是基于 Dart 语言编写的。本节课程里,我们就开始进行 Dart 语言的基础语法学习。本文将主要介绍:

  • Dart 的特点及简单介绍
  • Dart 的数据类型、操作符、变量常量
  • Dart 的运算符、流程控制语句
  • Dart 的函数(方法)、类
  • Dart 的泛型、接口等

1 Dart 简单介绍

1.1 为什么要介绍 Dart?

Google 计划未来的 Flutter 将会是移动应用、Web 应用、PC 应用等平台的跨平台高性能框架,也是未来的 Fuchsia 操作系统的主要框架,而 Flutter 是基于 Dart 编程语言编写的一个跨平台框架,所以一些语法是基于 Dart 语法来使用的,学习 Flutter 就要先了解 Dart。

1.2 什么是 Dart?

简单介绍下 Dart 语言。

Dart 是 Google 公司推出的编程语言,属于应用层编程语言,于 2011 年就已经亮相了。Dart 也是一门面向对象的语言,语法和 Java、C、JavaScript 很像。Dart 里所有的类都可以看成是对象,是单继承,动态类语言。Dart 可以进行移动应用、Web应用、服务器应用、PC 应用、物联网应用的开发等等,还在不断拓展开发平台,所以可以说 Dart 在各个平台领域“无所不能”。我们的主角 Flutter 就是基于 Dart 语言编写的。

Dart的应用

1.3 Dart 的特性

接下来看下 Dart 的特性。

  • 语法简单明了,开发速度快、效率高,学习成本低。
  • 简单但是功能强大,可以开发 Web、移动端、PC、服务器端、物联网等平台应用。
  • 编译执行速度快,拥有自己的 Dart VM,在移动端和 Web 上拥有高性能。
  • 全平台语言,可移植。Dart 类似于中间件语言,可以编译成不同平台的原生代码,可以很方便地扩展成跨平台应用语言,如 Android 和 iOS 平台。
  • 语言的结构融合了 Java、C、JavaScrpit 的特点,并结合 React 响应式编程的思维规范进行构建的一个现代化编程语言。

1.4 Dart 的语法特点

  • 面向对象的语言,一切数据类型、API 都是对象,都继承自 Object 类;
  • 强类型语言,同时也是动态类型语言。对不确定类型的可以定义成一个动态类型;
  • Dart 没有设置定义访问域的关键字,如果某个变量或者方法、类的名称以"_"开头,说明这个变量或者方法、类是私有的,外部不可以调用使用;
  • Dart 有入口函数:main(){…};类似于Java的public void main(String[] args){…};
  • Dart 吸收了很多现代编程语言的特点,加入了很多便捷的语法支持,可以明显缩减代码量和提高可读性;
  • 拥有 Future 和 Streams 使用方式,可以进行类似 RxJava 式的使用。

2 Dart 的关键字

好了,说了这么多,接下来该进入正题,我们来学习一些具体知识。 首先看下 Dart 的关键字(33 个保留字,17 个内置标志符)。

33 个 Dart 保留字:

关键字
assertbreakconstcontinuecasecatchclass
defaultelseenumextendsfinalfinallyfalse
forisinnewrethrowreturnsuperdo
switchthrowtrytypedefthistruevar
voidwhilewithtypedefthis

17 个 Dart 内置标志符:

关键字
abstractascovariantdeferreddynamicexportexternal
factorygetimplementsimportlibraryoperatorpart
setstatictypedef

6 个 Dart2 新增异步功能关键字:

关键字
asyncasync*awaitsync*yieldyield*

25 个 Dart 特有关键字(和 Java 语言相比):

关键字
asassertasyncasync*awaitconstcovariant
deferreddynamicexportexternalfactorygetin
islibraryoperatorpartrethrowsetsync*
typedefvaryieldyield*

3 Dart 的数据类型

我们先看一个官方给的最基础的 Dart 例子,例如我们新建一个 demo.dart 类:

// 这是程序执行的入口
main() {
  var number = 30; // 定义变量number并进行赋值初始化
  printNumber(number); // 调用方法
}

// 定义方法printNumber
printNumber(num aNumber) {
  print('The number is $aNumber.'); // 在控制台打印输出内容
}

这个例子涵盖了 Dart 的一个基础的语法结构,有入口、有变量声明、赋值、定义方法、调用方法、传递参数、数据类型、变量引用等等。

那么接下来我们看下 Dart 支持的几种基本数据类型:numbers(num)、String、bool、List 集合、Map 集合、runes(用于在字符串中表示 Unicode 字符)、symbol。

numbers(num)类型是表示数值型的数据类型,包括 int 和 double 类型两种。num 是 int 和 double 类型的父类。其中 int 整数值一般范围在 -2^53 和 2^53 之间;double 是 64 位双精度浮点型数据类型。举个例子:

void main() {
  //定义int和double类型
  int a = 6;
  double b = 3.18;
  print('$a ,$b');

  // String转int
  int twoInt = int.parse('2');
  // String转double
  var twoDouble = double.parse('2.2');
  print('$twoInt ,$twoDouble');

  // int转String
  String intToString = 2.toString();
  // double转String,后面需加入保留小数点位数
  String doubleToString = 3.23456.toStringAsFixed(2);
  print('$intToString,$doubleToString');

  //自动四舍五入
  String fiveString = 2.12832.toStringAsFixed(2);
  print(fiveString);
}

输出结果为:

6 ,3.18
2 ,2.2
2,3.23
2.13

大家可以在 DartPad 上进行操作:https://dartpad.dartlang.org

String 类型

大家应该都很熟悉,字符串类型。

  • Dart 字符串是 UTF-16 编码的字符序列,可以使用单引号或者双引号来创建字符串。
  • 可以在字符串中使用表达式,用法是这样的: ${expression}。
  • 可以使用 + 操作符来把多个字符串链接为一个,当然也可以不用加号,多个带引号的字符串挨着写就可以了。
  • 使用三个单引号或者双引号也可以创建多行字符串。
  • 使用 r 前缀可以创建一个原始字符串。

再来看一个例子:

void main() {
  //单引号和双引号定义
  String singleString = 'A singleString';
  String doubleString = "A doubleString";
  print('$singleString ,$doubleString');

//使用$字符引用变量,使用{}引入表达式
  String userS = 'It\'s $singleString';
  String userExpression = 'It\'s expression,${singleString.toUpperCase()}';
  print('$userS');
  print('$userExpression');

//使用引号字符串邻接来拼接或者使用+号连接字符串
  String stringLines =
      'String ' 'concatenation' " works even over line breaks.";
  String addString = 'A and ' + 'B';
  print('$stringLines');
  print('$addString');

//使用三个引号(单引号或双引号)来创建多行字符串
  String s3 = '''
You can create
multi-line strings like this one.
''';
  String s33 = """This is also a
multi-line string.""";
  print('$s3');
  print('$s33');

//使用r为开头,显示定义一个原始字符串
  String s = r"It is a \n raw string.";
  print('$s');
}

输出结果为:

A singleString ,A doubleString
It's A singleString
It's expression,A SINGLESTRING
String concatenation works even over line breaks.
A and B
You can create
multi-line strings like this one.

This is also a
multi-line string.
It is a \n raw string.

bool 类型

用于定义 true 或 false 的数据类型,很简单。需要区别注意的是有些写法在 Dart 里不支持。

var name = 'Tom';
if (name) {
  // JavaScript可以这样写,Dart不行
  print('He is Tom!');
}

// JavaScript可以这样写,Dart不行
if (1) {
  print('A line Data.');
} else {
  print('A good Data.');
}

List 集合

Dart 里使用 List 来表示数据集合结构。

void main() {
  //定义初始化一个集合
  var list = [1, 2, 3];
  List listData = [5, 6, 7];
  print(list.length);
  print(list[0]);
  //集合数据赋值
  listData[1] = 8;
  print(listData[1]);
  //如果在集合前加了const关键字,集合数据不可以进行操作
  var constantList = const [1, 2, 3];
  List datas = List();
  datas.add('data1');
  datas.addAll(['data2', 'data3', 'data4', 'data5', 'data6']);
  //输出第一个元素
  print(datas.first);
  // 获取最后一个元素
  print(datas.last);
  // 获取元素的位置
  print(datas.indexOf('data1'));
  // 删除指定位置元素
  print(datas.removeAt(2));
  //删除元素
  datas.remove('data1');
  //删除最后一个元素
  datas.removeLast();
  // 删除指定范围元素,含头不含尾
  datas.removeRange(0, 2);
  //删除指定条件的元素
  datas.removeWhere((item) => item.length > 3);
  // 删除所有的元素
  datas.clear();
  //其他方法可以自己尝试
}

Map 集合

Map 集合存储数据特点就是键值对(key-value)形式。key 是唯一的,value 允许重复。看一个实例:

void main() {
  //定义一个map并赋值
  var gifts = {
    // Keys      Values
    'first': 'dog',
    'second': 'cat',
    'fifth': 'orange'
  };

  var nobleGases = {
    // Keys  Values
    2: 'a',
    10: 'b',
    18: 'b',
  };
  //定义一个map并赋值
  Map map = Map();
  map['first'] = 'a-value';
  map['second'] = 'b-value';
  map['fifth'] = 'c-value';
  Map nobleGasesMap = Map();
  nobleGasesMap[2] = 'a-value';
  nobleGasesMap[10] = 'b-value';
  nobleGasesMap[18] = 'c-value';
  //指定键值对类型
  var nobleGases = new Map<int, String>();
  //获取某个key的value
  print(map['first']);
  //获取map大小
  print(map.length);
  //定义一个不可变的map
  final constantMap = const {
    2: 'a',
    10: 'b',
    18: 'c',
  };
  //其他API用法和List类似
}

Runes 类型

表示字符串 Unicode 编码字符(UTF-32 code points)等。

void main() {
  //看一个官方例子
  var clapping = '\u{1f44f}';
  print(clapping);
  print(clapping.codeUnits);
  print(clapping.runes.toList());

  Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
  print(new String.fromCharCodes(input));
}

Symbols 类型

使用 Symbol 字面量来获取标识符的 symbol 对象,也就是在标识符前面添加一个 # 符号。

 //看一个官方例子
 #radix
 #bar

4 Dart的操作符

看下 Dart 的操作符:

描述操作符
一元后缀符(unary postfix)expr++   expr--   ()   []   .   ?.
一元前缀符(unary postfix)-expr   !expr   ~expr   ++expr   --expr
乘法类型(multiplicative)*   /   %   ~/
加法类型(additive)+   -
位操作符(shift)<<   >>
按位与(bitwise AND)&
按位异或(bitwise XOR)^
按为或(bitwise OR)|
比较和类型测试(relational and type test)>=   >   <=   <   as   is   is!
等价(equality)==   !=
逻辑与(logical AND)&&
逻辑或(logical OR)||
是否是空(if null)??
条件运算符(conditional)expr1 ? expr2 : expr3
级联运算符(cascade)..
赋值(assignment)=   *=   /=   ~/=   %=   +=   -=   <<=   >>=   &=   ^=  

这些操作符用法和其他语言的含义和用法大同小异。

5 Dart 的流程控制语句

Dart 流程控制语句也不多,比较简单。主要有:

  • if 和 else
  • for 循环
  • while 和 do-while 循环
  • break 和 continue
  • switch 和 case
  • assert 断言(判断是否相等)

如果其中涉及到使用 try-catch 和 throw,可能会影响一些流程控制的跳转。

void main() {
  //if和else
  if (hasData()) {
    print("hasData");
  } else if (hasString()) {
    print("hasString");
  } else {
    print("noStringData");
  }

  //for循环
  var message = new StringBuffer("Dart is good");
  for (var i = 0; i < 6; i++) {
    message.write(',');
  }

  //while
  while (okString()) {
    print('ok');
  }
//do-while
  do {
    print('okDo');
  } while (!hasData());

  //break和continue
  while (true) {
    if (noData()) {
      break;
    }
    if (hasData()) {
      continue;
    }
    doSomething();
  }

  //switch和case
  var command = 'OPEN';
  switch (command) {
    case 'A':
      executeA();
      break;
    case 'B':
      executeB();
      break;
    case 'C':
      executeC();
      break;
    default:
      executeUnknown();
  }

  //Assert(断言)
  assert(string != null);
  assert(number < 80);
  assert(urlString.startsWith('https'));
}

Exceptions 异常捕获处理。

使用 throw 抛出异常。

throw new FormatException('Expected at least 2 section');

也可以抛出其他类型对象。

throw 'no data!';

使用 catch 捕获异常。

try {
  getData();
} on OutOfLlamasException {
  sendData();
} on Exception catch (e) {
  print('Unknown data Exception: $e');
} catch (e) {
  print('Some Exception really unknown: $e');
}

使用 rethrow 可以把捕获的异常给重新抛出。

//给出一个官方例子
final foo = '';

void misbehave() {
  try {
    foo = "You can't change a final variable's value.";
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // rethrow重新抛出,允许main()里的函数继续捕获处理异常
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}

Finally 处理,和 Java 里的类似,不管是否出现异常,最终都要执行的方法写在这里。

try {
  getData();
} catch(e) {
  print('Error: $e');
} finally {
  //始终执行
  sendData();
}

6 Dart 的类和函数(方法)

类这个概念是面向对象里的,Dart 也依然保留。我们创建对象需要创建类对象,可以使用 new 关键字,也可以不使用:

var map=Map();
var map2=new Map();

调用类方法:

var map=Map();
  map.length;
  //通过 对象.方法 的形式来调用使用方法

使用 ?. 来替代 . 可以避免当左边对象为 null 时抛出异常:

  a?.name = 'Tom';

关于获取对象的类型,可以使用 Object 的 runtimeType 属性来获取实例的类型。

先看一个实例化对象,并获取和调用属性和方法的例子,和 Java 用法基本一致:

class Position {
  num x;
  num y;
  methodPosition(){
      ...
  }
}

void main() {
  var pos = new Position();
  pos.x = 5;//赋值
  print(pos.x);//取值
  pos.methodPosition();//调用方法
}

定义同名构造方法:

class Position {
  num x;
  num y;

  Position(num x, num y) {
    this.x = x;
    this.y = y;
  }
}
//也可以这样简化定义构造方法
class Point {
  num x;
  num y;

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

注意:Dart 的构造函数不可以继承,父类的构造函数也不可以继承。

Dart 也支持抽象函数(抽象类):

abstract class Dog {
  //可以定义变量和抽象方法

  void doSomething(); // 定义抽象方法
}

class GoodDog extends Dog {
  void doSomething() {
    //实现逻辑
  }
}

Dart 的类可以继承多个类,这个 Dart 的一大特点。Dart 也支持实现多个接口,使用 implements 关键字:

class Comparable {
  final _name;

  Comparable(this._name);

  String good1(who) => 'Hello';
}

class Location {
  Location();

  String good2() => 'World!';
}

class ImlClass implements Comparable, Location {
  // ...
}

Dart 通过 extends 来继承拓展类,子类可以重写父类方法,通过 supper 来引用父类方法。

class Product {
  void open() {
    //...
  }
   // ...
}

class SmartProduct extends Product {
  void open() {
    super.open();
    //重写加入新的逻辑
  }
  // ...
}
//也可以使用@override注解来表示重写了父类方法 

还有其他注解,如可以使用 @proxy 注解来避免警告信息。

Dart 也支持枚举类型 enum:

enum Color {
  red,
  green,
  blue
}
//使用时候直接调用
Color.blue

可以使用 with 关键字实现多继承:

//看一个官方例子
class Musician extends Performer with Musical {
  // ...
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

Dart 支持静态函数使用,使用时候直接类名.函数名即可。

class Position {

  static num getLongPosition() {
    return 20;
  }
}

void main(){
    //直接调用
    Position.getLongPosition();
}

7 Dart 的泛型和限制域

Java 中泛型使用 T 来表示,Dart 里同样可以使用 T 来表示泛型类型。

abstract class Dog<T> {
  T getDogByName(String name);
  setDogByname(String name, T value);
}

//也可以限制泛型继承自什么类等操作
class Foo<T extends SomeBaseClass> {...}

class Extender extends SomeBaseClass {...}

void main() {
  var someBaseClassFoo = new Foo<SomeBaseClass>();
  var extenderFoo = new Foo<Extender>();
  var foo = new Foo();
}

Dart 的库的引入和使用:Dart 使用 import 关键字来导入库和类。

import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';
//如果两个导入的库里的类有重名的,可以使用as关键字
import 'package:utils2/utils2.dart' as utils2;

//也可以只导入库的一小部分
//只导入foo库
import 'package:lib1/lib1.dart' show foo;

//除了foo,其他的都导入
import 'package:lib2/lib2.dart' hide foo;

//延迟载入库,可以减少APP启动时间,优化性能
import 'package:deferred/hello.dart' deferred as hello;
//延迟后,使用的时候使用loadLibrary()来调用
//在一个库上可以多次调用loadLibrary() 函数,只执行载入一次
greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

如果我们想自己创建声明一个库想被别人引用时候,可以用 library 声明:

 // 声明库,名字为abc
  library abc;
  // 导入需要用到的相关库
  import 'dart:html';
  //编写逻辑
  ...
  //如果需要的话,可以借助part关键字来实现部分需求

如果你想声明某个变量、常量、方法函数不能被外部调用,只需要在名字前加上 _ 下划线前缀即可。

8 Dart 的异步处理

Dart 支持异步编程操作,例如我们的网络请求、耗时操作都可以使用。可以使用 async 和 await 关键字来进行标识异步操作。

Dart 里也有 Future 和 Stream 对象进行异步操作,非常的强大和方便。

//例如用await来表示这个方法异步的,需要等待完成后才能继续执行后面的方法
await lookUpVersion()
//要使用 await,其方法必须带有 async 关键字:
checkVersion() async {
  var version = await lookUpVersion();
  if (version == expectedVersion) {
    //执行操作
  } else {
    //执行操作
  }
}
//我们也可以使用Future来修饰包转返回类型,这样我们可以支持数据的后续其他操作
Future<String> lookUpVersion() async => '1.6.0';

在 await 表达式中,表达式的返回值通常是一个 Future 类型;如果返回的值不是 Future,则 Dart 会自动把该值放到 Future 中返回。

Dart 的基础语法知识部分就大概这么多,还有很多细节,大家有兴趣可以进行深入研究使用方法。

总结

本节课主要是给大家讲解 Dart 的基础语法部分,为后续 Flutter 的开发学习奠定基础,以期更好地进行深入研究和开发。Dart 的语法比较简单,和 Java 类似,可以对照着理解,全面详细的学习用法后,可以为高效开发做好准备。主要注意点和建议如下:

  • 建议将例子进行编写实践下,使用开发工具输出下结果加深理解。
  • 学习完后,可以进行一个实践练习,也为学习下一课时作准备。
  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值