Dart语言学习笔记一-概览

此篇内容均来源于《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);
  }
}

你可能感兴趣的:(Dart语言学习笔记一-概览)