代码风格
命名规范:
变量,常量,方法名使用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);
}
}
函数式编程
函数编程包括:
- 定义匿名函数(lambda)
- 将函数当作参数传递
- 将函数赋值给变量
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
});
补充:
- 纯函数
函数无副作用,除了期望结果,不会产生其它影响。具有稳定性,只要是相同的输入永远有相同的输出
- 高阶函数
函数即为值,可作为参数,返回值,以及赋值给变量
- 柯里化
以下以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),
}
持续补充中...
参考资料: