前言

Dart 是由 Google 主导开发,于2011年10月公开;它的开发团队由 Google Chrome 浏览器 V8 引擎团队的领导者拉尔斯·巴克主持,目标在于成为下一代结构化 Web 开发语言

Flutter的dart使用通道调用Java代码 flutter/dart_javascript

Dart 也是一种面向对象语言,但是它采用基于类编程Dart设计目标应该是既对标 Java,也对标 JavaScript,Dart静态语法方面Java 非常相似,如类型定义、函数声明、泛型等,而在动态特性方面又和 JavaScript 很像,如函数式特性、异步支持等,因此 Flutter 便成为了跨平台行业一个热点

想要学习开发 Flutter 首先就要先了解 Dart 语言的基本概念

Dart 基本概念

Dart 是面向对象的语言,和许多面向对象语言有着很接近的语法,如果你学过 C++,C#,Java 那么你只需要很短的时间就可以掌握 Dart,并且 Dart 语言具有以下几个特点:

  • Dart 是谷歌开发的开源的面向客户端的开发语言
  • Dart 可帮助开发者开发富有表现力的,高性能的客户端应用;它具有功能强大的框架,灵活易用的工具。
  • 客户端友好,非常适合开发移动和 Web 应用

一个简单的Dart程序大概长这个样子:

// 定义函数
printInteger(int aNumber) {
 print('The number is $aNumber.'); // 打印输出
}

// 应用执行入口
main() {
 var number = 42; // 声明和初始化变量
 printInteger(number); // 调用函数
}
Dart 核心概念

如果你要深入学习 Dart 请谨记以下这些核心概念:

  • Dart 中所有变量都是对象(object),每个对象都是某个类的实例,包括 number, function, null 以及 object;所有的对象都继承自 Object 这个超类。
  • Dart 是强类型语言,尽管这样,声明变量也可以不指定变量类型
  • Dart 可以自动推断一个变量的类型,就像上面的例子 变量 nunber 被自动推断为 int 类型
  • 如果一个变量不确定是何种类型或者可以接受任何类型,那么你可以使用特殊类型:dynamic 来声明一个变量
/// Returns a Boolean representation for [arg], which must
/// be a String or bool.
bool convertToBool(dynamic arg) {
 if (arg is bool) return arg;
 if (arg is String) return arg == 'true';
 throw ArgumentError('Cannot convert $arg to a bool.');
}
  • Dart 支持泛型,比如: List (int类型元素的数组)、List (包含可能任何object类型元素的集合)
  • Dart 支持顶级函数(例如main()),以及绑定到类或对象的函数(分别是静态和实例方法)你还可以在函数内创建函数(嵌套函数或本地函数)
  • 类似地,Dart支持顶级变量,以及绑定到类或对象的变量(静态和实例变量);实例变量有时称为字段或属性
  • 与 Java,C# 等不同Dart 没有 public,protected 和 private 这些访问修饰符,私有变量或方法会以下划线(_)开头来表示
  • Dart 里的变量或标识符必须是以字母或下划线开头的字母、下划线、数字的组合
  • 注意区分表达式(expressions have runtime values)和语句(statements don’t have runtime values),;比如条件表达式: condition ? expr1 : expr2, 会返回值 expr1 或 expr2,比较下 if else 语句,不具有值;语句通常包含一个或多个表达式,但表达式不能直接包含语句
  • Dart 工具具有两种类型异常提醒:警告和错误;警告代表你的代码可能有问题,但是不会阻止程序的运行;错误分为编译错误和运行错误,前者会阻止程序的运行,后者则会在程序运行使抛出异常!

我们可以把 Dart 中的类可分为两大类: 泛型类非泛型类

  • 先说非泛型类也就是开发中接触最多的一般类,一般的类去定义一个变量的时候,它的实际就是这个变量的类型. 例如定义一个 Student 类,我们会得到一个 Student 类型
  • 泛型类比非泛型类要更加复杂,实际上一个泛型类可以对应无限种类型。为什么这么说,其实很容易理解;在定义泛型类的时候会定义泛型形参,要想拿到一个合法的泛型类型就需要在外部使用地方传入具体的类型实参替换定义中的类型形参
  • 我们知道在 Dart 中 List 是一个类,它不是一个类型;由它可以衍生成无限种泛型类型。例如List<String>、List<int>、List<List<num>>、List<Map<String,int>>
何为子类型

我们可能会经常在 Flutter 开发中遇到 subtype 子类型的错误: type 'String' is not a subtype of type 'num' of 'other'. 到底啥是子类型呢? 它和子类是一个概念吗?

首先给出一个数学归纳公式:

  • 如果 G 是一个有 n 个类型参数的泛型类,而A[i]是 B[i] 的子类型且属于 1…n 的范围,那么可表示为 G * G 的子类型,其中 A * B 可表示 A 是 B 的子类型。

我们一般说子类就是派生类,该类一般会继承它的父类(也叫基类);例如: class Student extends Person{//...},这里的 Student 一般称为 Person 的子类

子类型则不一样,我们从上面就知道一个类可以有很多类型,那么子类型不仅仅是想子类那样继承关系那么严格

子类型定义的规则一般是这样的: 任何时候如果需要的是 A 类型值的任何地方,都可以使用 B 类型的值来替换的,那么就可以说 B 类型是 A 类型的子类型或者称 A 类型是 B 类型的超类型

Dart 语言可选类型

Dart 中的类型实际上是可选的,也就是在 Dart函数类型,参数类型,变量类型是可以直接省略

sum(a, b, c, d) {//函数参数类型和返回值类型可以省略
  return a + b + c + d;
}

main() {
  print('${sum(10, 12, 14, 12)}');//正常运行
}

上述的 sum 函数既没有返回值类型也没有参数类型,可能有的人会疑惑如果 sum 函数最后一个形参传入一个 String 类型会是怎么样

答案是: 静态类型检查分析正常但是编译运行异常

sum(a, b, c, d) {
  return a + b + c + d;
}

main() {
  print('${sum(10, 12, 14, "12312")}');//静态检查类型检查正常,运行异常
}

//运行结果
Unhandled exception:
type 'String' is not a subtype of type 'num' of 'other' //请先记住这个子类型不匹配异常问题,因为在后面会详细分析子类型的含义,而且Dart、Flutter开发中会经常看到这个异常。

Process finished with exit code 255

虽然,可选类型从一方面使得整个代码变得简洁以及具有动态性,但是从另一方面它会使得静态检查类型难以分析

但是这也使得 dart 中失去了基于类型函数重载特性;我们都知道函数重载静态语言中比较常见的语法特性,可是在 dart 中是不支持

比如在其他语言我们一般使用构造器重载解决多种方式构造对象场景,但是 dart 不支持构造器重载,所以为了解决这个问题,Dart 推出了命名构造器的概念;那可选类型语法特性为什么会和函数重载特性冲突呢?

我们可以使用反证法,假设 dart 支持函数重载,那么可能就会有以下这段代码:

class IllegalCode {
  overloaded(num data) {

  }
  overloaded(List data){//假设支持函数重载,实际上这是非法的

  }
}

main() {
    var data1 = 100; 
    var data2 = ["100"];
    //由于dart中的类型是可选的,以下函数调用,根本就无法分辨下面代码实际上调用哪个overloaded函数。
    overloaded(data1);
    overloaded(data2);
}

如果仅从可选类型角度去考虑的话,实际上 dart 现在是可以支持基于类型的函数重载的,因为 Dart 有类型推导功能;如果 dart 能够推导出上述 data1 和 data2 类型,那么就可以根据推导出的类型去匹配重载的函数

实际上,Dart 官方在 Github 提到过 Dart 迁移到新的类型系统中,Dart 是可以支持函数重载的

我们喜欢 Flutter 的一点是,它不仅仅是谷歌的产品–它是一个 "所有人 "的产品开源意味着我们都可以参与其中,并与它的成功息息相关,无论是通过贡献新的代码或文档,创建赋予核心框架新的超能力的包,编写教导他人的书籍和培训课程,还是帮助组织活动和用户组

为了展示 Flutter 社区最佳状态,我们最近与 DevPost 合作赞助了一个Puzzle Hack 挑战,为开发者提供了一个机会,通过用 Flutter 重新想象经典的滑动拼图来展示他们的技能;这证明了网络、桌面和移动的完美结合;现在我们都可以在线或通过商店玩这些游戏