【自学flutter系列】dart语言学习概览

Flutter 是由Google开发的UI工具包,是采用了 Dart 来编写的框架和 widget。
因此咱们要学习Flutter开发,就有必要了解dart语言,不说精通,至少得对dart的一些语法有一些了解。
其实若是你之前有过其它程序开发经验,很快便能掌握dart语法。
和javascript相比, dart是一门强类型的语言,Dart 综合了动态语言和静态语言的特性。javascript

变量与内置类型

变量

声明变量前端

// 声明变量并赋值
var name = 'Bob'

// 若是声明时没有赋值, 默认值为null
String name; // name的值为null

final 与constjava

若是你之后不打算修改一个变量,使用 final 或者 const。 一个 final 变量只能赋值一次;一个 const 变量是编译时常量。python

const age = 123; // const 在代码编译时就已经肯定了变量的值
final age; // 默认为null
age = 123; // 第一次赋值为123
age = 234; // Error 报错, final只能赋值一次

const 关键字不只仅只用来定义常量。 有时也能够用来建立不变的值, 还能定义构造函数为 const 类型的,这种类型 的构造函数建立的对象是不可改变的。express

内置类型

Numbers

  • int 整数
  • double 浮点数
int x = 1;
double y = 2.1;

// x = '222' // 报错,x是整数

数字和字符串这间的转换编程

// String -> int
int strToInt = int.parse('1');
// String -> double
double strToDouble = double.parse('1.1');

// int -> String
String intToStr = 1.toString();

// double -> String
String doubleToStr = 3.14159.toStringAsFixed(2);

Strings

Dart 字符串是 UTF-16 编码的字符序列。 可使用单引号或者双引号来建立字符串json

var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";

// 在字符串中使用表达式 ${expression},若是表达式是个变量,能够省去{}。
// 相似JS里的 `abc${var}`
var s = 'string interpolation';
var p = '这是一个表达式${s}';
var k = '这是一个表达式$s';
// 和js同样,可使用+链接多个字段串
var t = s + p + k;

使用三个单引号或者双引号也能够 建立多行字符串对象segmentfault

var s1 = '''
You can create
multi-line strings like this one.
''';

var s2 = """This is also a
multi-line string.""";

Booleans(布尔值)

Dart 有一个名字为 bool 的类型。 只有两个对象是布尔类型的:true 和 false 所建立的对象, 这两个对象也都是编译时常量。数组

通俗地讲就是dart判断bool值就是只能用true和false,像JS的0, 1, null等都能判断表达式真假,dart不能。缓存

var name = 'Bob';
if (name) { // 这里dart会抛出一个异常, 表示name变量不是一个布尔值。
    // javascript 能够这样判断, dart 不能
    print('Bob');
}

Lists(列表)

至关于JS里的数组,表示为有序的集合。

Maps

至关于JS里的对象字面量, python里的字典.
Map 是一个键值对相关的对象。 键和值能够是任何类型的对象。

var gifts = {
// Keys      Values
  'first' : 'partridge',
  'second': 'turtledoves',
  'fifth' : 'golden rings'
};

// 使用 Map 构造函数也能够实现一样的功能
var gifts = new Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

runes

runes 表明字符串的 UTF-32 code points。

symbols

略过

Functions 函数 (方法)

在Dart中, function是一种类型为 Function 的对象,这意味着function能够赋值给变量,也能够当作其余function的参数。 这和Javascript中function比较像。

对于只有一个表达式的function, 可使用 => 形式 缩写:

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

dart语言函数(方法)有两种参数: 必需的和可选的。 必需的参数在参数列表前面, 后面是可选参数。

可选参数又能够分为命名参数或者基于位置的参数,可是这两种参数不能同时当作可选参数。

参数若是没有设置默认值, 默认值为null。

// 可选命名参数
enableFlags({bool bold, bool hidden}) {
  // ...
}

// 可选位置参数 把一些方法的参数放到 [] 中就变成可选 位置参数了
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

函数参数究竟是值传递,仍是地址传递(引用)呢?

// 参数传递简单的数字
void main() {
  int k = 5;
  
  print(k);
  test(k);
  print(k);
}

void test(int a) {
  a = 77;
  print(a);
}
// 返回的结果是
5
77
5

// 函数传递map
void main() {
  Map<int, String> k = {
    1: '123',
    2: '234'
  };
  
  print(k);
  test(k);
  print(k);
}

void test(Map a) {
  a[1] = 'kkkk';
  print(a);
}
// 返回的结果是
{1: 123, 2: 234}
{1: kkkk, 2: 234}
{1: kkkk, 2: 234}

具体原理也能够能够参照 https://blog.csdn.net/bbdxf/a...

  1. var a = 10;这种赋值语法的含义是a是指向一个内存对象10的引用(ref).
  2. var a = 10; var b=a; 则a,b都指向同一个内存对象,即引用同一个内存对象。可是a,b之间没有任何联系。
  3. 在2的状况下,修改a指向对象的值,b也会跟着改。(矛盾点也在这里!)
  4. 可是,Dart中不是全部的对象均可以修改的(mutable or immutable),其中number,String,bool等都是不可变类型,每次修改都是产生一个新的对象。而其余大部分对象都是mutable, 因此第3条的状况在面对immutable对象会表现不一致。

看起来和JS的函数参数传递是差很少的。按照JS传参理解的话就是:

简单的如数字,字符串,bool 是值传递。在函数内部对参数变量从新赋值,不会改变函数做用域外的值。

Lists, Maps, Functions, 对象等是按引用传递。在函数内部对参数变量从新赋值,函数做用域外的值也会相应地跟着改变

操做符

这节咱们主要关注下那些与JS语法中不同的那些操做符。其它的像 +, -, * , / , >, <, = ,%, ++, -- 等 这些操做符和js里彻底是同样的。

// 1 整除 ~/ 
// 至关于除数取整数部分, 
assert(5 ~/ 2 == 2) // 至关于JS里的 Math.floor(5/2)
assert(5 ~/ 3 == 1)

// as  类型转换
// is  若是对象是指定的类型返回 True
// is! 若是对象是指定的类型返回 False
// 只有当 obj 实现了 T 的接口, obj is T 才是 true。

if (emp is Person) { // Type check
  emp.firstName = 'Bob';
}

(emp as Person).firstName = 'Bob';

// 若是 emp 是 null 或者不是 Person 类型, 则第一个示例使用 is 则不会执行条件里面的代码,而第二个状况使用 as 则会抛出一个异常。

// 赋值操做符
// ??=  有点像是JS里 || 表达式赋值
a = value;   // 给 a 变量赋值
b ??= value; // 若是 b 是 null,则赋值给 b;
             // 若是不是 null,则 b 的值保持不变

// 条件表达式 ??
// 至关于js里的&&

// 级联操做符 ..
// 级联操做符 (..) 能够在同一个对象上 连续调用多个函数以及访问成员变量。
// 条件成员访问 ?.  和 . 相似,可是左边的操做对象不能为 null,例如 foo?.bar 
// 若是 foo 为 null 则返回 null,不然返回 bar 成员

querySelector('#button') // Get an object.
  ..text = 'Confirm'   // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));
  
// 和上面的代码和下面的代码功能同样:
var button = querySelector('#button');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

流程控制

流程控制和其它编程语言的基本上是同样的。
须要注意的是条件表达式(if...else...)的判断条件只能是True和false。

异常处理

Dart 提供了 Exception 和 Error 类型, 以及一些子类型。你还 能够定义本身的异常类型。 Dart 代码能够 抛出任何非 null 对象为异常,不只仅是实现了 Exception 或者 Error 的对象。

Throw 抛出异常

try...catch 捕获异常

Finally 要确保某些代码执行,无论有没有出现异常都须要执行

Classes 类

class Point {
    // 类属性
    num x;
    num y;
    // this 关键字指当前的实例。
    // 构造函数
    Point(this.x, this.y)
    // 至关于
    //Point(num x, num y) {
    //    this.x = x;
    //    this.y = y;
    //}
    // 命名构造函数
    Point.fromJson(Map json) {
      x = json['x'];
      y = json['y'];
      print('in Super Classes');
    }
    // 方法
    num distanceTo(Point other) {
      var dx = x - other.x;
      var dy = y - other.y;
      return sqrt(dx * dx + dy * dy);
    }
    
    // Getter, setters
    // 每一个实例变量都隐含的具备一个 getter, 若是变量不是 final 的则还有一setter。 
    // 你能够经过实行 getter 和 setter 来建立新的属性, 使用 get 和 set 关键字定义 getter 和 setter
}

// 调用超类构造函数

class ChildClass extends Point {
    // 采用
    ChildClass.fromJson(Map json) : super.fromJson(data) {
        print('in Child Classes')
    }
}

抽象类与抽象函数

// 使用 abstract 修饰符定义一个 抽象类—一个不能被实例化的类。 抽象类一般用来定义接口, 以及部分实现
abstract class Doer {
  // 定义一个抽象类
  void doSomething();
}

class EffectiveDoer extends Doer {
  void doSomething() {
      // 实现这个抽象类
  }
}

扩展类 (extends)

使用 extends 定义子类, supper 引用 超类

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  void test() {
      print('Television')
  }
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // 使用@override 注解来 代表你的函数是想覆写超类的一个函数
  @override
  void test() {
      print('SmartTelevision')
  }
}

枚举类型

// 使用 enum 关键字来定义枚举类型
enum Color {
  red,
  green,
  blue
}

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);

类变量和类函数

何为类变量和类函数? 即不需实例化该类,使用类名.便可使用的变量或函数

使用 static 关键字来实现类级别的变量和函数。

import 'dart:math';

class Point {
  num x;
  num y;
  Point(this.x, this.y);

  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
}

main() {
  var a = new Point(2, 2);
  var b = new Point(4, 4);
  var distance = Point.distanceBetween(a, b);
  assert(distance < 2.9 && distance > 2.8);
}

泛型

这个泛型对于前端开发人员来讲是个新概念。若是你查看 List 类型的 API 文档, 则能够看到 实际的类型定义为 List<E>。 这个 <…> 声明 list 是一个 泛型 (或者 参数化) 类型。 一般状况下,使用一个字母来表明类型参数, 例如 E, T, S, K, 和 V 等。

例如,若是你但愿一个 list 只包含字符串对象,你能够 定义为 List<String>, 这样你、 你的同事、以及所使用的工具 ( IDE 以及 检查模式的 Dart VM )能够帮助你检查你的代码是否把非字符串类型对象给放到 这个 list 中了。

另一个使用泛型的缘由是减小重复的代码。 泛型能够在多种类型之间定义同一个实现, 同时还能够继续使用检查模式和静态分析工具提供的代码分析功能。

var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
// 错误
names.add(42); 


// 减小代码量
// 对象缓存
abstract class ObjectCache {
  Object getByKey(String key);
  setByKey(String key, Object value);
}
// 缓存字符串
abstract class StringCache {
  String getByKey(String key);
  setByKey(String key, String value);
}
....

// 使用泛型后, 定义一个通用的实现
abstract class Cache<T> {
  T getByKey(String key);
  setByKey(String key, T value);
}
// T 是一个备用类型。这是一个类型占位符, 在开发者调用该接口的时候会指定具体类型


//  泛型函数

T first<T>(List<T> ts) {
  // ...Do some initial work or error checking, then...
  T tmp ?= ts[0];
  // ...Do some additional checking or processing...
  return tmp;
}

异步支持

Dart 有一些语言特性来支持 异步编程。 最多见的特性是 async 方法和 await 表达式。

Dart 库中有不少返回 Future 或者 Stream 对象的方法。 这些方法是 异步的。

是否是很眼熟。 async, await 是咱们在写JS中常常见到的呀。那在个人理解是:

dart中的Future和Stream对象就至关于JS中的Promise对象
async 方法和 await 表达式 使用的JS中的使用是同样的。

以上这些纯属我的学习记录,本人是一名前端开发,对JS比较熟悉,因此有些地方会套用些JS的语法来作说明

若有错误及不妥之处,欢迎评论留言指出。

上一篇: 【自学flutter系列】flutter 开发环境搭建

相关文章
相关标签/搜索