此篇内容均来源于《Dart编程语言》--[美]Gilad Bracha 著 戴虬 译
设计准则
1.1 万物皆对象
dart是一门由google开发并被批准为ECMA标准(ECMA-408)的通用编程语言。它可以用于构建web端、服务端和移动端应用程序。它是开源的,使用宽松的免费软件许可证(修改版BSD许可证)。Dart是完全面向对象的,使用类和单继承,可编译为JavaScript,语法风格是类C的。它支持接口、mixin、抽象类、泛型和可选类型。
Dart是一门纯面向对象的编程语言,这意味着Dart程序在运行时所处理的值都是对象,甚至包括数字,布尔值等基本数据,无一例外。
Dart坚持对所有数据统一处理,这方便了所有与语言相关的人员:语言的设计者,实现者,以及最重要的使用者。
1.2 面向接口编程,而非面向实现
关注对象的行为而非他的内部实现,这是面向对象编程语言的核心原则。虽然实现的不够完美,Dart却力图通过以下几种方式来维护这个原则。
- Dart的类型基于接口,而不是类。作为一项原则,任意类都隐含了一个接口,能够被其它类实现,不管其他类是否使用了同样的底层实现(部分core type例外,比如数字,布尔值与字符串)
- Dart没有final方法,允许重写几乎所有方法(同样,部分内置的操作符例外)。
- Dart把对象进行了抽象封装,确保所有外部操作都通过存取方法来改变对象的状态
- Dart的构造函数允许对对象进行缓存,或者从子类型创建实例,因此使用构造函数并不意味着绑定了一个具体的实现。
1.3 类型可选
- 类型在语法层面上来说是可选的
- 类型对运行时语义没有影响
类型可选照顾了那些不愿意与类型系统打交道的开发者。因此而选择Dart的开发者,完全可以把Dart当成一门动态类型语言。虽然类型可选,但只要代码中有类型注解,就意味着代码有了额外的文档,所有的编码人员都会从中受益。类型注解同时让工具能更好的配合开发者的开发工作。
对于可能存在的类型不一致和遗漏,Dart会给出警告,不会报错。这些警告的程度和性质都经过校准,不会铺天盖地的出现,确保真正对开发者有益。同时,Dart编译器不会拒绝一段缺少类型或类型不一致的程序。
概述
2.1最简单的表达式
3
这个表达式的值是整数3.
mymain(){
print("hello world");
print(3);
print(3+4);
print((3+4)*6);
print(1+2*2);
print(1234567890987654321*1234567890987654321);
}
结果:
hello world
3
7
42
5
6172041164457194081
Exited
最后一个例子比较有趣, 书上的结果是1524157877457704723228166437789971041.Dart中的整数很像数学里的数字,他们没有32位或64位可代表的最大值的限制,其大小的唯一限制是可用内存。
Dart不仅支持整数,也支持浮点数,字符串,布尔值,许多内置类型都有很简便的语法
dataType() {
3.14159; // 一个浮点数
'a string';
true;
false; //布尔值
[]; //一个空列表
[
0,
1.0,
false,
'a',
[2, 2.0, true, "b"]
]; // 有5个元素的列表 ,最后一个也是列表。
}
Dart的列表相当于其他语言的数组,Dart是用List来表示数组的。
list(){
print([1,2,3].length);// 3
print([].length);// 0
print([].isEmpty); // true
print(['a'].isNotEmpty);// true
}
2.2 函数
一个Dart程序的执行总是开始于对main() 函数的调用。每个函数都由函数头与函数体组成。函数的头部定义了函数的名称与参数。
twice(x) => x * 2;
声明了一个名为twice的函数,并有一个名为x的参数。该函数返回x乘以2的结果。我们可以这样来执行它
twice(2); // 4
以上函数调用的结果是4.这个twice函数有两部分,一部分是由函数名与形式参数组成的函数签名,另一部分就是跟在=>后面的只包含了一个表达式的函数体。另一种更传统的书写方式是:
twice(x) {
return x * 2;
}
另一个函数
// 使用了if语句
max(x, y) {
if (x > y)
return x;
else
return y;
}
可以简写成
// 使用条件表达式
max(x, y) => (x > y) ? x : y;
另一个更加复杂的函数
maxElement(a) {// 接收一个列表a,并返回一个最大值
var currentMax =// 声明一个currentMax变量,并对其进行初始化(Dart程序中每个变量必须显示声明)
a.isEmpty ? throw 'Maximal element undefined for empty arrray' : a[0];
// 异常是使用throw语句抛出的。throw关键字后面跟着一个定义抛出内容的表达式。在Dart中,
// 任何类型值都可以被抛出,不要求他们是特定的Exception类型。
for (var i = 0; i < a.length; i++) {
currentMax = max(a[i], currentMax);
}
return currentMax;
}
2.3 类
Dart允许你在类外部定义函数与变量。虽然如此,Dart是一门纯面向对象的语言。我们前面看到的所有值,包括数字, 字符串,布尔值,列表甚至函数本身都是Dart中的对象。所有这些对象都是某个类的实例。像length,isEmpty这些操作, 甚至[]索引操作符,都是对象的方法。
现在我们学习如何编写一个类。请看这个Point类,它代表了直角坐标系的点:
class Point {
var x, y;
Point(a, b) {
x = a;
y = b;
}
}
要创建一个Point类的实例,我们可以用new表达式来调用它的构造函数:
var origin = new Point(0, 0);
var aPoint = new Point(3, 4);
var anotherPoint = new Point(3, 4);
以上3行创建了3个新的不一样的Point实例,特别是,aPoint和anotherPoint是两个不同的对象。每个对象都有唯一标识,他们通过这个标识来区分彼此。
每个Point的实例都有各自的x和y变量的副本,可以通过点符号来访问他们:
printPoint(){
print(origin.x);
print(origin.y);
print(aPoint.x);
print(aPoint.y);
print(anotherPoint.x);
print(anotherPoint.y);
}
结果如下:
0
0
3
4
3
4
变量x和y的值是由构造函数的实际参数来设置的,而构造函数是由new调用的。将构造函数的形式参数直接赋值给同名的字段,这种方式非常普遍,所以Dart为此提供了一种特殊的语法糖:
class Point{
var x, y;
Point(this.x, this.y);
}
新版的Point与原版完全相同,但更简洁。我们再给它添加一些行为:
class Point{
var x, y;
Point(this.x, this.y);
scale(factor) => new Point(x * factor, y * factor);
}
这个版本多一个scale方法,它接收一个定义比例系数的参数factor,并返回一个新的点。新的点的坐标是根据当前点的坐标按照facor缩放而得来的。
print(aPoint.scale(2).x); // 6
print(anotherPoint.scale(3).y); // 12
另外一个有趣的操作就是对点进行加法操作:
class Point{
var x, y;
Point(this.x, this.y);
scale(factor) => new Point(x * factor, y * factor);
operator + (p) => new Point(x + p.x, y + p.y);
}
结果:
print((aPoint + anotherPoint).y);// 8
2.4 静态成员
Dart也支持静态成员。我们可以给Point添加一个计算两点间距离的静态方法
static distance(p1, p2) {
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
static修饰符表明此方法不针对某个特定实例,它无法访问实例变量x和y,因为实例变量对于每个Point实例都是不同的。
Dart代码用库作为模块化的基本单元。每个库都定义了一个的命名空间,这个命名空间包含所有在库中声明的实体的名称,其他库的实体也能被导入进来。Dart核心库中声明的实体,都会被隐含的导入到所有的Dart库中。
import 'dart:math';
class Point {
var x, y;
Point(this.x, this.y);
scale(factor) => new Point(x * factor, y * factor);
operator +(p) => new Point(x + p.x, y + p.y);
static distance(p1, p2) {
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
}