Dart 学习笔记

135 阅读3分钟

代码风格

命名规范:

变量,常量,方法名使用lowerCamelCase

文件名使用lowercase_with_underscores

类名称,类型定义(typeof),类型参数,枚举名称以及注解名称使用UpperCamelCase

typedef Predicate<T> = bool Function(T value);

@Foo()
class A { ... }
// 省略括号可使用lowerCamelCase命名
@foo
class B { ... }

package:导入语句放在项目导入语句之前,且遵循字母顺序。

把导出语句放在所有导入语句之后。

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'util.dart';

export 'src/error.dart'

所有控制流结构都需要使用大括号,除非执行体适合在一行中实现。

if (overflowChars != other.overflowChars) {
  return overflowChars < other.overflowChars;
}

if (arg == null) return defaultValue;

基础

dart程序入口为main方法,方法参数可选

void main(List<String> args) {}

类成员变量为空需要添加可空标识?,否则必须构造方法中赋值

对于未赋值的成员变量,需要初始化:

class Person {
  int? age;
  int name;
  Person(this.name);
}

class Person {
  int age;
  Person() : age = 12 + 16;
}

Person person = Person()

或:

class Person {
  int age;
  Person.init() : age = 12 + 16
}

Person person = Person.init()

方法支持可选参数

void run({int speed, String place}) {}
void main() {
  run(place: '');
}

dart没有可见修饰符,通过名称前添加_表明对应变量,方法是否公开。若需要获取未被公开的变量值,可使用get方法

class Person {
  String _id;
  String get id => _id;
}
void main() {
  Person person = Person();
  person.id;
}

dart没有interface字段,使用抽象类代替接口

abstract Person {
  int get number;
}
class Student extends Person {
  @override
  int get number = 1
}
class Worker extends Person {
  @override
  int get number = 2
}

子类不继承父类的实现

abstract Person {
  int get number;
}
class Worker extends Person {
  String name  
  Worker(this.name);
  @override
  int get number = 2
  fun talk() {}
}
class Teacher extends Worker {
  Teacher(super.name);
  @override
  int get number = 2;
}

可通过工厂方法创建对象实现工厂模式

abstract Person {
  int get number;
  factery Person(String type) {
    if(type == 'Worker') {
      return Worker();
    }
    if(type == 'Teacher') {
      return Teacher();
    }
    throw 'build failure'
  }
}
void main() {
  Teacher teacher = Person('Teacher');
  teacher.number;
}

集合

使用集合字面量

var points = <Point>[];
var addresses = <String, Address>{};
var counts = <int>{};

使用.isEmpty替代.length

使用for in替代foreach,若使用已存在并且将循环变量作为参数的函数,使用foreach更方便

people.forEach(print);

使用toList代替List.from来获取List

print(iterable.toList().runtimeType);

// 要更改类型可使用from
print(List<int>.from(iterable)).runtimeType);

使用### whereType按类型过滤集合

list.whereType<int>()

集合类型转换尽量不要使用cast,因为cast转换得到的是惰性集合,惰性集合每次使用都需要对集合中的元素进行一次类型检查。可以使用List.from来取代cast,或者在访问时再进行类型转换

void printEvens(List<Object> objects) {
  for (final n in objects) {
    if ((n as int).isEven) print(n);
  }
}

函数式编程

函数编程包括:

  1. 定义匿名函数(lambda)
  2. 将函数当作参数传递
  3. 将函数赋值给变量
int calculate(int a, int b) => a + b;
void getResult(Function(int a, int b) fun) {}
void main() {
  getResult(calculate(1, 2));
}

函数式编程操作集合:

students
  .where((sudent) {
    return student.score > 60
  })
  // 取3个
  .take(3)
  .map((sudent) {
    student.name
  });

补充:

  1. 纯函数

函数无副作用,除了期望结果,不会产生其它影响。具有稳定性,只要是相同的输入永远有相同的输出

  1. 高阶函数

函数即为值,可作为参数,返回值,以及赋值给变量

  1. 柯里化

以下以Js为🌰

function add(x, y) {
  return x + y;
}

var currying = function(x) {
  return function(y) {
    return x + y;
  }
}

let f = currying(1)
f(2)
f(3)
f(4)

// 未使用柯里化
add(1, 2)
add(1, 3)
add(1, 4)

并发

void read() {
   File file = File('path');
   Future<String> content = file.readAsString();
   content.then((value) => {
     print(value)
   });
}
// 不会阻塞该行代码的执行
print('continue')

如果需要阻塞,则可以使用async , await

void read() async {
  File file = File('path');
  String content = await file.readAsString();
  print(content),
}

持续补充中...

参考资料:

dart.cn/codelabs/da…

zxfcumtcs.github.io/2019/11/17/…