Flutter开发指南之理论篇:Dart语法01(数据类型,变量,函数)

总目录

Flutter开发指南之理论篇:Dart语法01(数据类型,变量,函数)
Flutter开发指南之理论篇:Dart语法02(运算符,循环,异常)
Flutter开发指南之理论篇:Dart语法03(类,泛型)
Flutter开发指南之理论篇:Dart语法04(库,异步,正则表达式)


 Dart是一门面向对象语言,它针对web 和移动设备开发进行了优化,主要特点为:

  • 一切皆对象!无论是数字,函数还是null,所有对象继承自Object类;
  • 声明一个变量时可以不指定具体类型,Dart可以自动推断类型;
  • Dart支持顶层函数,函数是一等对象,且函数可作为参数传递;
  • Dart使用_开头表示私有属性,没有关键字publicprotectedprivate

1. 数据类型

 在Dart中,支持的数据类型有:NumberStringBooleanListMapSetRune,这些类型都可以被初始化为字面量,它们的主要特点如下:

1.1 Number

 Dart使用int,double和num表示数字类型,其中,num可以是整数或浮点数的类型。

// 整型,整数值不大于64位
var age = 33
int age = 33

// 浮点型,64位双精度浮点数
var salary = 18888.88
double salary = 18888.88

// num是int和double的父类
// 具体类型由dart自动推导
num age = 33
num salary = 18888.88

 字符串与数字类型转换:

// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

1.2 String

 Dart的字符串类型的编码格式为UTF-16,通过单引号或者双引号(等价)创建。如果需要实现多行字符串对象,可以连续三个单引号或者三个双引号(等价);或者使用r前缀创建“原始raw”字符串,以保留字符串格式,比如不会对’\n’等进行转移。

  • 创建String
// 普通字符串
var country = 'china'
var country = "china"

// 多行字符串
// 会保持格式,但对于转义字符会进行转义
var comment = '''
    Your point is great.
    I support you!
'''
var comment = """
    Your point is great.
    I support you!
"""
// 使用r前缀,保持字符串原始格式
String news = r"Trump failed, \n biden won!"
  • 判断两个String是否相等
var country1 = 'china'
var country2 = "china"
// 判断两个字符串相等,使用 ==
// 字符串中引入变量值,使用 ${},如果不是表达式可以去掉{}
print("is equal = ${country1==country2}")

1.3 Boolean

 Dart使用bool类型表示布尔值,只有字面量true和false是布尔类型。

var isUsed = false

// 等价于
// bool isUsed = false

1.4 List

 Dart使用List类型表示一个列表,即有序对象的集合。

var list = [1, 2, 3]; 

// 等价于
// List<int> list = [1, 2, 3];

 如果需要定义一个List类型的编译时常量,可以使用const。

var constantList = const [1, 2, 3];
// constantList[1] = 1; // 取消注释会引起错误。

1.5 Set

 Dart使用Set类型表示一个集合,这个集合的元素是唯一。


var countries = {'China', 'America', 'Canada', 'France'}

// 等价于
// Set<String> countries = {'China', 'America', 'Canada', 'France'}

 要创建一个空集,使用前面带有类型参数的{},或者将{}赋值给Set类型的变量。

var countries = <String>{};
// Set<String> names = {}; // 这样也是可以的。
// var names = {}; // 这样会创建一个 Map ,而不是 Set 。

// 添加元素
countries.add('Germany');
countries.addAll(countries);

// 获取长度
var setLength = elements.length

 同样,如果需要定义一个Set类型的编译时常量,可以使用const。

fianl countries = const {'China', 'America', 'Canada', 'France'}

// countries.add('Germany'); 报错

1.6 Map

 Dart使用Map用来关联keys和values的对象(键值对集合),其中,keys 和 values 可以是任何类型的对象,并且在一个Map对象中一个key只能出现一次,但是 value可以出现多次。

// 创建一个空的Map对象
var personInfos = {}
var personInfos = Map()

// 创建一个Map对象,并赋值
var personInfos = {
    'name': 'zhangsan',
    'sex': 'male',
    'age': 66
}

var personInfos = Map();
personInfos['name'] = 'zhangsan';
personInfos['sex'] = 'male';
personInfos['age'] = '66';

// 创建一个常量Map
final var personInfos = const {
    'name': 'zhangsan',
    'sex': 'male',
    'age': 66
}
// personInfos['hometown']='china' 会报错,常量不允许修改

1.7 Rune

 Dart使用Rune来表示字符串中的UTF-32编码字符。由于 Dart 字符串是一系列 UTF-16 编码单元, 因此要在字符串中表示32位Unicode值需要特殊语法支持,Unicode 定义了一个全球的书写系统编码, 系统中使用的所有字母,数字和符号都对应唯一的数值编码。表示 Unicode 编码的常用方法是\uXXXX, 这里 XXXX 是一个4位的16进制数,比如心形符号 (♥) 是\u{2665}。

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

输出结果为:
👏
[55357, 56399]
[128079]
♥ 😅 😎 👻 🖖 👍

2. 变量

2.1 变量

 在dart中,声明一个变量有四种方式: var, dynamic, object具体类型,它们的区别如下:

  • var的类型由dart自动推导,一旦初始化它的数据类型不可变;
  • dynamic动态任意类型,编译阶段不检查,被赋值后仍然可被赋值为其他类型;
  • object动态任意类型,编译阶段检查,被赋值后仍然可被赋值为其他类型;
  • 指定具体的类型,跟Java声明一个变量一样。

示例如下:

var name;
name = 'Bob'; // 类型为String
name = 123;   // 报错,初始化后类型被锁定
// 等价于 var name = 'Bob';
// 等价于 String name = 'Bob';(指定具体类型)

dynamic name;
name = 'Bob'; // 类型为String
name = 123;   // 类型为num
name.test();  // 如果name对象的test()方法不存在,编译阶段不会报错,运行时报错

object name;
name = 'Bob'; // 类型为String
name = 123;   // 类型为num
name.test();  // 如果name对象的test()方法不存在,编译阶段报错

 注:dart中一切皆对象,没有初始化的变量默认值都是null。

2.2 final,const和static

(1)final和const

finalconst均可用于声明一个变量不可变(常量),它们的特点如下:

  • const要求在声明时初始化且初始值必须为编译时常量
  • final在类中声明变量不要求初始化,可以在构造函数参数列表中初始化,初始值也不要求为编译时常量;
  • const,final被初始化后,变量的值将不能被改变,被const声明的变量又被成为常量;
  • const,final均可被用于文件和类中,当const用于声明类成员变量时必须同时被声明为static。

const的使用场景:

// 场景一:定义一个常量
// 在定义时初始化且初始值为编译时常量
// 一旦赋值不允许修改,可以省略变量的类型,如var,int等

void main() {
  const a = 1;             // 数值,字符串等类型常量
  const b = 'hello';
  const c = a;
  
  const b = a > 1 ? 2 : 1; // 表达式常量,所有值都是编译时常量
  
  const a = const [1,2,3]; // 集合常量,=的右边必须用const修饰
  
  const b = ConstObject(2); // 对象常量,对象的构造函数必须用const修饰
  b.log();
}

class ConstObject {
  final value;
  const ConstObject(this.value);
  log() {
    print(value);
  }
}

// 场景二:作为修饰符
// 如果修饰集合,要求集合的每个元素均为编译时常量且不允许更改;
// 如果修饰构造函数,要求该类的所有成员必须使用final声明;

void main() {
  var c = 2;
  var a = const [c,2,3];    //ERROR, 集合元素必须是编译时常数。
  
  const a = const [1,2,3];  
  a[1] = 2;                //ERROR, 不允许修改。
}


class ConstObject {
  
  final value;
  int value2;           //ERROR, 必须是 final 变量。
  
  const ConstObject(this.value);
  
  log() {
    print(value);
  }
}

// 场景三:声明一个类的全局常量
// const用于声明类成员变量时必须同时被声明为static
// 被声明的变量是编译时常量,是类的成员变量
class ConstObject {
  
  const static value = 2;
  
  ConstObject(this.value);
  
  log() {
    print(value);
  }
}

final的使用场景:


// 场景一:文件中的声明一个不可变量
// 必须在声明时赋值,一旦赋值不允许修改,可以省略变量的类型,如var,int等
void main() {
  final c; // 报错,必须声明时赋值
  c = 99  
  
  final c = 99;
  c = 66  // 报错,赋值后不可变
}

// 场景二:类中声明一个不可变量
// 可以在构造函数或初始化列表中初始化,一旦赋值不允许修改,可以省略变量的类型,如var,int等
class TestClass {
  
  final value;
  TestClass(this.value);
  
  // 等价于
  // final value = 2;
  // TestClass();
  
  log() {
    print(value);
  }
}

(3)static

static只能用于声明类的成员变量,它的用法与Java中的static一样。

class TestClass {
  
  // 值是编译时常量,所有类共享该变量(即全局变量)
  static const value = 2;
  
  // 值不是编译时常量,所有类共享该变量(即全局变量)
  static final value;
  
  TestClass(this.value);
  
  log() {
    print(value);
  }
}

3. 函数

 前面说到,Dart是一门真正面向对象的语言,即一切皆对象,包括函数!在Dart中,函数是一等对象,函数可作为顶层函数,类的成员函数,甚至可以被赋值给变量或者作为参数传递给其他函数,其中,当作为顶层函数时其对类的属性和方法可见。【注意:函数返回值没有类型推断,如果函数指定返回值类型,默认当作dynamic处理。

3.1 函数定义

[类型] 函数(类型 参数1, 类型 参数2,...) {  
    return 返回值
}

 其中, 返回类型可以省略,Dart会自动推到返回值类型。如果返回类型为void,return语句可省略。 所有函数都会返回一个值。 如果没有明确指定返回值,函数体会被隐式的添加return null;语句,即函数的返回值为null。

int add(int a, int b) {
    return a+b;
}

// 等价于
add(int a, int b) {
    return a+b;
}

// 等价于
// 当函数体只有一句表达式(expr)时,可以使用=>expr简化
// =>expr语法是{return expr;}的简写
add(int a, int b) => a+b;

3.2 函数参数

 Dart的函数有两种参数类型:requiredoptional。required 类型参数在参数最前面,随后是optional类型参数。

  • required 类型

 required类型参数使用@required注解标识,被标注的参数在函数被调用时必须传入,否则会报错。@required注解通常可以省略,但是当标识命令参数时,不能省略。

String saySomeThing(@required String who, @required String msg) {
    print('Someone is $who, want to say $msg')
}

// 等价于
String saySomeThing(String who, String msg) {
    print('Someone is $who, want to say $msg')
}
  • optional类型

 optional类型分为命名可选参数和位置可选参数,其中,命令可选参数使用{}包裹,位置可选参数使用[]包裹。被标注为可选的参数在函数调用时,可以不传入且不会报错。

 命名可选参数:

void printPersonInf({@require String name, int age=22, String sex}) {
    print('person info = $name, ${age.toString()}, $sex')
}

// 调用
// printPersonInf(name: "jiangdg", age: 18, sex: male);
// 其中,除了name不可省略,其他均可省略

 位置可选参数:

String say(String from, String msg, [String device='HUAWEI']) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

// 调用
// 忽略传入device参数,分析器不会报错
// var result = say("jiangdg", "Hello World!");

 注:从上述示例中可知,两种可选参数均支持传入默认值,使用=赋值即可。

3.3 函数的用法

 Dart中函数是一等对象,函数可作为顶层(顶级)函数,类的成员函数,甚至可以被赋值给变量或者作为参数传递给其他函数。

  • a. 函数作为变量

 Dart中的函数时一个Function类型的对象,因此可以被赋值给一个变量:

var message = (str) {
    print(str);
}

// 调用message
message('download success')
  • b. 函数作为另一个函数参数

 函数作为一个对象,因此可以被作为参数传递:

void execute(var callback) {
    callback();
}

// 执行execute
// 传入的函数对象为匿名函数或称Lambda表达式
execute(()=>print(‘Hello World!));
  • c. 匿名函数(闭包,lambda函数)

 所谓匿名函数,就是没有名字的函数。匿名函数,又被称为Lambda函数或Closure(闭包),它和其它函数一样,除了没有名字,也拥有形参列表,可选参数。函数体为:

([[Type] param1[, …]]) {
  codeBlock;
};

 举个例子:

(num x) => x;//没有函数名,有必需的位置参数x
(num x) {return x;}//等价于上面形式
(int x, [int step]) => x + step;//没有函数名,有可选的位置参数step
(int x, {int step1, int step2}) => x + step1 + step2;没有函数名,有可选的命名参数step1、step2

var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

// 特别的,如果匿名函数体只有一条语句,可以使用箭头缩写
// 因此这类函数又称为箭头函数
// 上述代码等价于
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item)=>print('${list.indexOf(item)}: $item'));

闭包

 闭包是一个函数对象,它被定义再其它函数内部,并且能够访问外部方法内的局部变量,并持有其状态。通过闭包,可以将其暴露出去,提供给外部访问。上述匿名函数的例子,实际上就是闭包的体现,但为了理解,接下来看下面的例子:

void main() {
    // 获取闭包
    // log()是闭包的外部函数
    val logFunc = log();
    for(var i = 0; i<5; i++) {
        // 执行闭包
        logFunc()
    }
}

// 声明一个无返回值类型,无形参的函数
log() {
    int count = 0;
    
    // 内部声明一个函数,即闭包
    // 将持有外部函数的局部变量count的状态
    printCount() {
        print(count++);
    }
    // 返回闭包
    return printCount;
}

打印结果为:0,1,2,3,4

 由于闭包被定义在一个函数内部,因此又称其为嵌套函数,Dart语言允许多层函数嵌套,而嵌套函数的作用域可为:

// 顶层作用域变量
bool topLevel = true;

void main() {
  // main函数作用域变量
  var insideMain = true;

  void myFunction() {
    // myFunction函数作用域变量
    var insideFunction = true;

    void nestedFunction() {
      // nestedFunction函数作用域变量
      var insideNestedFunction = true;

      // nestedFunction函数中可以访问上面所有层级中的变量。
      print(topLevel);
      print(insideMain);
      print(insideFunction);
      print(insideNestedFunction);
    }
  }
}
  • 顶层函数和main()函数

 Dart中有一种特别,它不需要在类中定义,而是直接基于dart文件顶层定义函数。main函数就是一个顶层函数。任何应用都必须有一个顶级main()函数,作为应用服务的入口。main()函数返回值为空,参数为一个可选的List<String>。示例如下:

//顶层函数,不定义在类的内部
main() {
  print('hello dart');
}

class Number {
    static int getValue() => 100;//static修饰定义在类的内部。
}

 注:static关键字用于声明一个静态函数,且必须定义在类的内部。

参考文献:

1. Dart编程语言中文网

已标记关键词 清除标记
<p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">通过本课程学习您可以学习到Dart语言如下知识:</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第1章 Dart语言概述</strong>:Dart语言简介、Dart语言支持平台开发Flutter为什么选择Dart语言。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第2章 开发环境搭建</strong>:下载Dart SDK、Windows下安装Dart SDK、macOS下安装Dart SDK、Visual Studio Code开发工具、IntelliJ IDEA开发工具。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第3章 完成个Dart程序</strong>:动动手写一个HelloWorld、Dart源代码文件组织结构、Visual Studio Code调试Dart代码、IntelliJ IDEA调试Dart代码。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第4章 Dart语法基础</strong>:标识符、关键字、变量、常量、注释、库。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第5章 Dart数据类型</strong>:数值类型、字符串、数据类型相互转换、布尔类型和枚举类型</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第6章 运算符</strong>:算术运算符、算术赋值运算符、关系运算符、逻辑运算符、位运算符、条件运算符、类型检查运算符。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第7章 控制语句</strong>:分支语句、循环语句、跳转语句。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第8章 函数</strong>:函数声明、可选参数、头等函数(first-class function)、匿名函数。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第9章 类</strong>:类声明、getter和setter访问器、构造函数、静态变量和静态方法、级联符号。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第10章 继承与多态</strong>:Dart中的继承实现、调用父类构造函数、成员变量的覆盖(Override)、方法的覆盖(Override)、多态、混入(Mixins)。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第11章 抽象类与接口</strong>:抽象类、接口、Dart中隐式接口、实现接口。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第12章 数据容器</strong>:List容器、Set容器、Map容器、泛型。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第13章 异常处理</strong>:捕获异常、try-on捕获异常、try-catch捕获异常、try-on-catch捕获异常、使用finally代码块、手动抛出异常、自定义异常类。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">第14章 异步编程</strong>:Dart异步处理机制、案例:同步函数实现读取文件、案例:异步函数实现读取文件、Future对象。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><img src="https://img-bss.csdnimg.cn/202010220122229073.jpg" alt="" width="880" height="5582" /></p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p>
相关推荐
程序员的必经之路! 【限时优惠】 现在下单,还享四重好礼: 1、教学课件免费下载 2、课程案例代码免费下载 3、专属VIP学员群免费答疑 4、下单还送800元编程大礼包 【超实用课程内容】  根据《2019-2020年中国开发者调查报告》显示,超83%的开发者都在使用MySQL数据库。使用量大同时,掌握MySQL早已是运维、DBA的必备技能,甚至部分IT开发岗位也要求对数据库使用和原理有深入的了解和掌握。 学习编程,你可能会犹豫选择 C++ 还是 Java;入门数据科学,你可能会纠结于选择 Python 还是 R;但无论如何, MySQL 都是 IT 从业人员不可或缺的技能!   套餐中一共包含2门MySQL数据库必学的核心课程(共98课时)   课程1:《MySQL数据库从入门到实战应用》   课程2:《高性能MySQL实战课》   【哪些人适合学习这门课程?】  1)平时只接触了语言基础,并未学习任何数据库知识的人;  2)对MySQL掌握程度薄弱的人,课程可以让你更好发挥MySQL最佳性能; 3)想修炼更好的MySQL内功,工作中遇到高并发场景可以游刃有余; 4)被面试官打破沙锅问到底的问题问到怀疑人生的应聘者。 【课程主要讲哪些内容?】 课程一:《MySQL数据库从入门到实战应用》 主要从基础篇,SQL语言篇、MySQL进阶篇三个角度展开讲解,帮助大家更加高效的管理MySQL数据库。 课程二:《高性能MySQL实战课》主要从高可用篇、MySQL8.0新特性篇,性能优化篇,面试篇四个角度展开讲解,帮助大家发挥MySQL的最佳性能的优化方法,掌握如何处理海量业务数据和高并发请求 【你能收获到什么?】  1.基础再提高,针对MySQL核心知识点学透,用对; 2.能力再提高,日常工作中的代码换新貌,不怕问题; 3.面试再加分,巴不得面试官打破沙锅问到底,竞争力MAX。 【课程如何观看?】  1、登录CSDN学院 APP 在我的课程中进行学习; 2、移动端:CSDN 学院APP(注意不是CSDN APP哦)  本课程为录播课,课程永久有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化。  下载方式:电脑登录课程观看页面,点击右侧课件,可进行课程资料的打包下载。
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页