Dart语言基础

mac2024-11-04  13


学习一门编程语言,首页要了解它的历史和特点。Dart是Google公司推出的编程语言,于2011年就已经亮相了。Dart也是一门面向对象的语言,语法和Java,C,JavaScript很像。所以会Java语言,学习Dart一般会快一些。Dart里所有的类都可以看成是对象,是单继承,动态类语言。可以进行移动应用、Web应用、服务器应用、PC应用、物联网应用的开发等等,还在不断的拓展开发平台。我们的主角Flutter就是基于Dart语言编写的,未来的Flutter将会是移动应用、Web应用、PC应用等平台的跨平台高性能框架。接下来的课程里,我们就开始进行Dart语言的基础语法学习。本文将主要介绍:

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

Dart简单介绍

为什么要介绍Dart?因为Flutter是基于Dart编程语言编写的一个跨平台框架。所以一些语法是基于Dart语法来使用的,Google计划未来的Flutter将会是移动应用、Web应用、PC应用等平台的跨平台高性能框架,也是未来的Fuchsia操作系统的主要框架。那么接下来就简单介绍下Dart语言。

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

接下来看下Dart的特性:

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

Dart的语法特点:

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

Dart的关键字

好了,说了这么多,接下来改进入正题了,进入学习一门语言需要掌握的一些基本知识。首先看下Dart的关键字:(33个保留字,17个内置标志符)

33个Dart保留字:

关键字assertbreakconstcontinuecasecatchclassdefaultelseenumextendsfinalfinallyfalseforifinisnewnullrethrowreturnsuperdoswitchthrowtrytypedefthistruevarvoidwhilewith

17个Dart内置标志符:

关键字abstractascovariantdeferreddynamicexportexternalfactorygetimplementsimportlibraryoperatorpartsetstatictypedef

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

关键字asyncasync*awaitsync*yieldyield*

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

关键字asassertasyncasync*awaitconstcovariantdeferreddynamicexportexternalfactorygetinislibraryoperatorpartrethrowsetsync*typedefvaryieldyield*

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

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)=   *=   /=   ~/=   %=   +=   -=   <<=   >>=   &=   ^=  

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

Dart的流程控制语句

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

if和elsefor循环while和do-while循环break和continueswitch和caseassert断言(判断是否相等)

如果其中涉及到使用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(); }

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(); }

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关键字来实现部分需求

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

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

最新回复(0)