Dart 2.1 的细节变化笔记总结(一)
编码风格默认规范
UpperCamelCase 每个单词的首字母都大写,包含第一个单词。
lowerCamelCase 除了第一个字母始终是小写(即使是缩略词),每个单词的首字母都大写。
lowercase_with_underscores 只是用小写字母单词,即使是缩略词,并且单词之间使用 _ 连接。
UpperCamelCase
风格
-
要 使用
UpperCamelCase
风格命名类型。
Classes(类名)、 enums(枚举类型)、 typedefs(类型定义)、以及 type parameters(类型参数)应该把每个单词的首字母都大写(包含第一个单词),不使用分隔符。
PS:这里包括使用元数据注解的类。,如果注解类的构造函数是无参函数,则可以使用一个 lowerCamelCase 风格的常量来初始化这个注解。
-
要 使用
UpperCamelCase
风格类型作为扩展名
extension MyFancyList<T> on List<T> { ... }
lowercase_with_underscores
风格
-
要 在
库
,包
,文件夹
,源文件
中使用lowercase_with_underscores
方式命名。
library peg_parser.source_scanner;
import 'file_system.dart';
import 'slider_menu.dart';
-
要 用
lowercase_with_underscores
风格命名库和源文件名。
DO name import prefixes using lowercase_with_underscores
.
import 'dart:math' as math;
import 'package:angular_components/angular_components' as angular_components;
import 'package:js/js.dart' as js;
lowerCamelCase
风格
- 类成员、顶级定义、变量、参数以及命名参数等 除了第一个单词,每个单词首字母都应大写,并且不使用分隔符
var count = 3;
HttpRequest httpRequest;
void align(bool clearItems) {
// ...
}
- 推荐 使用 lowerCamelCase 来命名常量。
const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');
class Dice {
static final numberGenerator = Random();
}
把超过两个字母的首字母大写缩略词和缩写词当做一般单词来对待
class HttpConnection {}
class DBIOPort {}
class TVVcr {}
class MrRogers {}
var httpRequest = ...
var uiHandler = ...
Id id;
使用 _, __, etc. 作为无用回调参数
futureOfVoid.then((_) {
print('Operation complete.');
});
顺序
要 把 “dart:” 导入语句放到其他导入语句之前。
要 把 “package:” 导入语句放到项目相关导入语句之前。
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'util.dart';
要 把导出(export)语句作为一个单独的部分放到所有导入语句之后。
import 'src/error.dart';
import 'src/foo_bar.dart';
export 'src/error.dart';
避免 单行超过 80 个字符。
对所有流控制结构使用花括号。
变量
- 所有变量引用的都是 对象,每个对象都是一个 类 的实例。数字、函数以及
null
都是对象。除去null
以外(如果你开启了 空安全), 所有的类都继承于 [Object][] 类。 - 在声明变量时指定类型是可选的,因为 Dart 可以进行类型推断
- 开启了 空安全,变量在未声明为可空类型时不能为
null
。你可以通过在类型后加上问号 (?
) 将类型声明为可空。例如,int?
类型的变量可以是整形数字或null
。如果你 明确知道 一个表达式不会为空,但 Dart 不这么认为时,你可以在表达式后添加!
来断言表达式不为空(为空时将抛出异常)。例如:int x = nullableButNotNullInt!
- 显式地声明允许任意类型,使用
Object?
(如果你 开启了空安全)、Object
或者 特殊类型dynamic
将检查延迟到运行时进行。 - Dart 支持泛型,比如 List<int>(表示一组由 int 对象组成的列表)或 List<Object>(表示一组由任何类型对象组成的列表)。
- Dart 支持顶级函数(例如 main 方法),同时还支持定义属于类或对象的函数(即 静态 和 实例方法)。你还可以在函数中定义函数(嵌套 或 局部函数)。
- Dart 支持顶级函数(例如 main 方法),同时还支持定义属于类或对象的函数(即 静态 和 实例方法)。你还可以在函数中定义函数(嵌套 或 局部函数)。
- Dart 支持顶级 变量,以及定义属于类或对象的变量(静态和实例变量)。实例变量有时称之为域或属性。
- Dart 没有类似于 Java 那样的 public、protected 和 private 成员访问限定符。如果一个标识符以下划线 (_) 开头则表示该标识符在库内是私有的。
var name = 'Bob';
Object name = 'Bob';
String name = 'Bob';
10.默认值
在 Dart 中,未初始化的变量拥有一个默认的初始化值:null
。(如果你未迁移至 空安全,所有变量都为可空类型。)即便数字也是如此,因为在 Dart 中一切皆为对象,数字也不例外。
int? lineCount;
assert(lineCount == null);
assert() 的调用将会在生产环境的代码中被忽略掉。在开发过程中,assert(condition) 将会在 条件判断 为 false 时抛出一个异常。
- Late variables 和 Kotlin 很像,延迟初始化
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
- Final 和Const
如果你不想更改一个变量,可以使用关键字 final 或者 const 修饰变量,这两个关键字可以替代 var 关键字或者加在一个具体的类型前。一个 final 变量只可以被赋值一次;一个 const 变量是一个编译时常量(const 变量同时也是 final 的)。顶层的 final 变量或者类的 final 变量在其第一次使用的时候被初始化。
const arr=[];
var arr2 = const[];
final foo = const[];
这三种区别,只能 arr2=[1];
- 内置类型
-
Numbers (
int
,double
) -
Strings (
String
) -
Booleans (
bool
) -
Lists (也被称为 arrays)
-
Sets (
Set
) -
Maps (
Map
) -
Runes (常用于在
Characters
API 中进行字符替换) -
Symbols (
Symbol
) -
The value
null
(Null
) -
Object
: The superclass of all Dart classes exceptNull
. -
Future
andStream
: Used in asynchrony support. -
Iterable
: Used in for-in loops and in synchronous generator functions. -
Never
: Indicates that an expression can never successfully finish evaluating. Most often used for functions that always throw an exception. -
dynamic
: Indicates that you want to disable static checking. Usually you should useObject
orObject?
instead. -
void
: Indicates that a value is never used. Often used as a return type.
Dart2.1 int to double 小变化
看注释不解释
import 'dart:math' as math;
class Circle {
double radius;
Circle(this.radius);
double get area => math.pi * math.pow(radius, 2);
}
void main() {
// Before Dart 2.1, you had to provide a trailing `.0` – `42.0` – when
// assigning to fields or parameters of type `double`.
// A value like `42` was not allowed.
print(Circle(2.0).area); // Before Dart 2.1, the trailing `.0` is required.
// With Dart 2.1, you can provide whole-number values when assigning to
// a double without the trailing `.0`.
print(Circle(2).area); // Legal with Dart 2.1
}
mixin, with, on 的使用
mixin AnswerMixin {
int get answer => 42;
@override
String toString() => '[ $runtimeType ]';
}
class Answer with AnswerMixin {}
void main() {
print('''
*
* Simple usage of `mixin`
*
''');
printAnswer(Answer(), 'Use `with` to include a mixin');
print('''
*
* More advanced usage of `mixin`
*
''');
printAnswer(
LogAnswer(),
'Include many mixins by separating with commas. '
'`$LoggingAnswerMixin` prints every time `answer` is accessed.');
print('''
*
* The order in which mixins are included matters.
*
''');
printAnswer(LogVerifyAnswer(), 'In this case, log then verify.');
printAnswer(VerifyLogAnswer(), 'In this case, verify then log.');
print('''
*
* You can extend classes that include mixins, too.
*
''');
printAnswer(DeltaLogVerifyAnswer(), 'Verify will fail.');
printAnswer(DeltaLogVerifyAnswer(1), 'Verify will succeed.');
}
void printAnswer(AnswerMixin obj, String description) {
print(obj);
print('- $description');
print('answer: ${obj.answer}');
print('');
}
/// [LoggingAnswerMixin] can only be used as a mixin when the superclass
/// (or one of the mixins that comes before it in a "with" clause) implements
/// [AnswerMixin].
mixin LoggingAnswerMixin on AnswerMixin {
@override
int get answer {
var value = super.answer;
print(' LOG: `answer` property was accessed');
return value;
}
}
class LogAnswer with AnswerMixin, LoggingAnswerMixin {}
mixin VerifyingAnswerMixin on AnswerMixin {
@override
int get answer {
var value = super.answer;
if (value == 42) {
print(' VERIFY: Invalid Result!');
} else {
print(' VERIFY: valid result');
}
return value;
}
}
class LogVerifyAnswer
with AnswerMixin, LoggingAnswerMixin, VerifyingAnswerMixin {}
class VerifyLogAnswer
with AnswerMixin, VerifyingAnswerMixin, LoggingAnswerMixin {}
abstract class DeltaAnswer with AnswerMixin {
final int delta;
DeltaAnswer(this.delta);
@override
int get answer => super.answer + delta;
}
class DeltaLogVerifyAnswer extends DeltaAnswer
with LoggingAnswerMixin, VerifyingAnswerMixin {
DeltaLogVerifyAnswer([int delta = 0]) : super(delta);
}
结果,可以讨论下这里,确实有点不好理清逻辑
* * Simple usage of `mixin` *
[ Answer ]
- Use `with` to include a mixin
answer: 42
* * More advanced usage of `mixin` *
[ LogAnswer ]
- Include many mixins by separating with commas. `LoggingAnswerMixin` prints every time `answer` is accessed.
LOG: `answer` property was accessed
answer: 42
* * The order in which mixins are included matters. *
[ LogVerifyAnswer ]
- In this case, log then verify.
LOG: `answer` property was accessed
VERIFY: Invalid Result!
answer: 42
[ VerifyLogAnswer ]
- In this case, verify then log.
VERIFY: Invalid Result!
LOG: `answer` property was accessed
answer: 42
* * You can extend classes that include mixins, too. *
[ DeltaLogVerifyAnswer ]
- Verify will fail.
LOG: `answer` property was accessed
VERIFY: Invalid Result!
answer: 42
[ DeltaLogVerifyAnswer ]
- Verify will succeed.
LOG: `answer` property was accessed
VERIFY: valid result
answer: 43
所有语言课本上的开胃菜
void main() {
var i = 20;
print('fibonacci($i) = ${fibonacci(i)}');
}
/// Computes the nth Fibonacci number.
int fibonacci(int n) {
return n < 2 ? n : (fibonacci(n - 1) + fibonacci(n - 2));
}
result
fibonacci(20) = 6765