前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >上手指南 | Dart,随用随查

上手指南 | Dart,随用随查

作者头像
345
发布2022-02-15 09:35:17
1.8K0
发布2022-02-15 09:35:17
举报
文章被收录于专栏:用户4077185的专栏

最近打算要入坑 Flutter,所以在此进行记录,随用随查;

不要怂,就是干,

一个简单的 Dart 程序

代码语言:javascript
复制
main(){
  var number = "Hello World";
  printInteger(number);
}
//定义一个函数
printInteger(int aNumber){
  print('The number is $aNumber');
}

重要的概念

在学习 Dart 语言时,应该基于以下事实和概念

  • 任何保存在变量中的都是一个对象;所有的对象都对应一个类的实例,函数 和 null 都是对象,所有对象基于 Object 类
  • 虽然 Dart 是强类型的,但是 Dart 可以进行类型推断,如上面代码变量 number 被推断为 int 类型;如果要明确说明不需要任何类型, 需要使用特殊类型 dynamic
  • Dart 支持泛型,如 List<int> , List<dynamic>(任何类型的对象列表)
  • Dart 支持顶级函数 main() ,同样函数绑定在类或对象上(分别是 静态函数实例函数 )。 以及支持函数内创建函数 ( 嵌套局部函数 ) 。
  • Dart 支持顶级变量
  • dart 没有关键字 public ,protected 和 private,如果以 _ 开头,则相对于库是私有的
  • 三目运算符:条件 condition ? Expr1 : expr2
  • 类型问题:警告和错误,警告表示代码可能无法正常工作,但不会阻挡程序的执行,错误可能是编译或者运行时的错误,编译时错误会阻止代码的执行,运行时错误会导致代码在执行中引发异常(#exception)

关键字

abstract 2

dynamic 2

implements 2

show 1

as 2

else

import 2

static 2

assert

enum

in

super

async 1

export 2

interface 2

switch

await 3

extends

is

sync 1

break

external 2

library 2

this

case

factory 2

mixin 2

throw

catch

false

new

true

class

final

null

try

const

finally

on 1

typedef 2

continue

for

operator 2

var

covariant 2

Function 2

part 2

void

default

get 2

rethrow

while

deferred 2

hide 1

return

with

do

if

set 2

yield 3

应该避免这些单词作为标识符

  • 带有 1 的单词为 上下文关键字,仅在特定位置具有含义,他们在任何地方都是有效标识符
  • 带有 2 的为 内置标识符,这些关键字大多数地方都是有效的标识符,不能用于类型名称 和 import 前缀
  • 带有 3 的是 Dart 1.0 发布后添加的异步支持相关的更新,作为限制类保留字。

变量

代码语言:javascript
复制
dynamic name = "345"; // name 被推断为 String类型
String name = "345";//显式声明

dynamic:该类型具有所有可能的属性和方法,一个变量被 dynamic 修饰,相当于告诉系统,我知道这个类型到底是什么。使用后再编译时不会推断数据的类型,但是运行时会推断。

默认值

未初始化的变量默认值是 null,即使是数字类型也是 nullDart 中一切皆是对象

Final 和 Const

使用过程中从来都不会被修改的变量,可用 final 或者 const。final 变量的值只能被设置一次,const 变量在编译时就已经固定。

内建类型

  • Number:有两种类型1,int,整数值不大于 64位;double 双精度浮点数
  • String::Dart 字符串是一组 UTF-16 单元序列,字符串通过单引号 或者 双引号创建

可使用 + 将字符串连接为一个;使用三个或三个双引号可实现多行字符串对象的创建

使用 r"" 前缀,可以创建“原始 raw 字符串”

  • Boolean: true and false
  • List:(也被称为 Array)

var list = [1, 2, 3]; var list = [1, 2, 3]; assert(list.length == 3); assert(list[1] == 2);

list[1] = 1; assert(list[1] == 1);

在 list 之前添加 const 关键字,可定义 List 类型的编译时常量

代码语言:javascript
复制
var constantList = const [1, 2, 3];

Map:用来关联 key 和 value,同一个 map 中 key 只能出现一次

代码语言:javascript
复制
var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};
  • Set:set 是一个元素唯一的集合
代码语言:javascript
复制
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
var names = <String>{};
// Set<String> names = {}; // 这样也是可以的。
// var names = {}; // 这样会创建一个 Map ,而不是 Set 。
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);

var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';  
  • Rune: (用于在字符串中表示 Unicode 字符)

在 Dart 中, Rune 用来表示字符串中的 UTF-32 编码字符

表示 Unicode 编码的常用方法是, \uXXXX, 这里 XXXX 是一个4位的16进制数。 例如,心形符号 (♥) 是 \u2665。 对于特殊的非 4 个数值的情况, 把编码值放到大括号中即可。 例如,emoji 的笑脸 (�) 是 \u{1f600}

  • Symbol

Symbol 对象表示 Dart 程序中声明的运算符或者标识符,你一般不会使用到他

Null-aware

Dart的Null-aware来自于Dart 1.12正式版本 , 存在即是合理,既然有这样运算符,说明他在一定程度上节省了我们的代码

整个运算符是专门用来处理 null 值得,他会提供空指针的相关操作

代码语言:javascript
复制
a = b ?? c;

//若 a 为 null,则将 b 赋值给 a
a ?? = b;

//当 x 不为 nul 时,调用 fun 函数
a?.fun();

函数

Dart 是一门真正的面对对象语言,甚至其中的函数也是对象,并且有他的类型 Function。意味着函数可以被赋值给变量,或者作为参数传递给其他函数,也可以把 Dart 类的实例当做方法来调用

代码语言:javascript
复制
isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}
//如果只有一句话,可简洁写法
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

=> *expr* 语法是 { return *expr*; } 的简写。 => 符号 有时也被称为 箭头 语法 ,箭头后面只能是一个表达式;

  • 调用时可选参数定义函数时,使用{param1,param2,...},放在参数列表的最后面,用于指定可选参数,例如
代码语言:javascript
复制
const Scrollbar({Key key, @required Widget child,bool bold})

使用 @required 表示参数是 required 性质的命名参数。

  • 位置可选参数
代码语言:javascript
复制
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

将参数放在 [] 中,来标记参数是可选的。表示该参数可以不传

  • 默认参数值
代码语言:javascript
复制
// bold 值为 true; hidden 值为 false.
void abc(bool bold = false);

接受一个 list 和 map,并指定参数的默认值

  • main() 函数
代码语言:javascript
复制
void main(){
}
// 这样运行应用: dart args.dart 1 test
void main(List<String> arguments) {
  print(arguments);
}

main 函数返回值为 空,参数为一个可选的 List<String>

  • 匿名函数

多数函数是有名字的,比如 main() 等,dart 可以创建没有名字的函数,这种函数被称为匿名函数有时候也被称为 lambda 或者 closure。匿名函数可以赋值到一个变量中,例如:在一个集合中可以添加或者删除一个匿名函数

代码语言:javascript
复制
main(){
  var list = [];
  list.add(1);
  list.add(2);
  list.add(3);
  list.add(4);
  
  list.forEach((num){
    print('位置:${list.indexOf(num)} ;值:$num');
  });
}

上面定义了一个 无类型参数num 的匿名函数,list 遍历时,每次都会调用这个函数,并将值传递给到匿名函数中。

如果只有一句话,可使用如下写法:

代码语言:javascript
复制
list.forEach((num)=>print('位置:${list.indexOf(num)} ;值:$num'));
  • 函数的赋值与传递
代码语言:javascript
复制
main(){
  //将匿名函数赋值给变量
  var one = (num)=>print(' 值:$num');
  one(10);
  
  //将普通函数赋值给变量
  var two = abc;
  two(20);
  
  //将匿名函数传递给普通函数
  abc2((str) => print("abc $str"));
}

void abc2(fun(String str)){
 fun("输出-------》");
}

void abc(num){
  print("哈哈哈:$num");
}
  • 词法作用域

dart 是一门词法作用域的编程语言。

简单的说变量的作用域在编写代码的时候就已经确定了,花括号内就是变量的可见作用域

代码语言:javascript
复制
bool topLevel = true;

void main() {
  var insideMain = true;

  void myFunction() {
    var insideFunction = true;

    void nestedFunction() {
      var insideNestedFunction = true;

      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}

内部可以访问所有的变量,一直到顶级作用域内的变量。

  • 词法闭包

闭包即一个函数对象。即使函数的调用在他原始的作用域之外,依然能访问他在词法作用域内的变量

代码语言:javascript
复制
/// 返回一个函数,返回的函数参数与 [addBy] 相加。
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

void main() {
  // 创建一个加 2 的函数。
  var add2 = makeAdder(2);

  // 创建一个加 4 的函数。
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}
  • 测试函数是否相等
代码语言:javascript
复制
void foo() {} // 顶级函数

class A {
  static void bar() {} // 静态方法
  void baz() {} // 示例方法
}

void main() {
  var x;

  // 比较顶级函数。
  x = foo;
  assert(foo == x);

  // 比较静态方法。
  x = A.bar;
  assert(A.bar == x);

  // 比较实例方法。
  var v = A(); // A的1号实例
  var w = A(); // A的2号实例
  var y = w;
  x = w.baz;

  // 两个闭包引用的同一实例(2号),
  // 所以它们相等。
  assert(y.baz == x);

  // 两个闭包引用的非同一个实例,
  // 所以它们不相等。
  assert(v.baz != w.baz);
}
  • 返回值

所有函数都会有返回值,如果没有明确返回值,函数体会被隐式的添加 return null;语句

扩展函数,属性

代码语言:javascript
复制
extension StringExt on String {
  double toDouble() {
    return double.parse(this);
  }
  int toInt() {
    return int.parse(this);
  }
}

Object扩展:
extension ObjectExt on Object {
  bool isNullOrEmpty() {
    if (this is String)
      return (this as String).isEmpty;
    else if (this is Iterable) return (this as Iterable).isEmpty;
    return this == null;
  }
}

泛型扩展:
extension AllExt<T> on T {
  T apply(f(T e)) {
    f(this);
    return this;
  }

  R let<R>(R f(T e)) {
    return f(this);
  }
}

//扩展属性
extension SizeExtension on num {

  double get w => 10.0;

  double get h => 10.0;
}

运算符

  • Dart 定义的运算符如下:

Description

Operator

一元后缀

*expr*++ *expr*-- () [] . ?.

一元前缀

-*expr* !*expr* ~*expr* ++*expr* --*expr*

multiplicative

* / % ~/

additive

+ -

shift

<< >> >>>

bitwise AND

&

bitwise XOR

^

bitwise OR

|

relational and type test

>= > <= < as is is!

equality

== !=

logical AND

&&

logical OR

||

if null

??

conditional

*expr1* ? *expr2* : *expr3*

cascade

..

assignment

= *= /= += -= &= ^= etc.

上表中,多数运算符可被重载

  • 条件表达式
代码语言:javascript
复制
*condition* ? *expr1* : *expr2*

如果条件为 true, 执行 expr1 (并返回它的值): 否则, 执行并返回 expr2 的值。

代码语言:javascript
复制
*expr1* ?? *expr2*

如果 expr1 是 non-null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。

  • 级联运算符

级联运算符可以对一个对象进行一些了操作,除了调用函数,还可以访问同一对象上的字段属性,

代码语言:javascript
复制
void main() {
  new A()
	  ..a1()
	  ..a2();
}
class A{
	void a1(){
		print('a1');
	}
	
	void a2(){
		print('a2');
	}
}
//a1  a2

级联运算符可进行嵌套

代码语言:javascript
复制
final addressBook = (AddressBookBuilder()
      ..name = 'jenny'
      ..email = 'jenny@example.com'
      ..phone = (PhoneNumberBuilder()
            ..number = '415-555-0100'
            ..label = 'home')
          .build())
    .build();

控制流程语句

  • if and else
  • for loops
代码语言:javascript
复制
for (var i = 0; i < 5; i++) {
  message.write('!');
}

也可使用 forEach,或者 for-in

代码语言:javascript
复制
candidates.forEach((candidate) => candidate.interview());
代码语言:javascript
复制
var collection = [0, 1, 2];
for (var x in collection) {
  print(x); // 0 1 2
}
  • while and do-while loops
  • break and continue
  • switch and case

和 java 基本类似,可以比较整数,字符串,或者编译时常量,比较的对象都是同一个实例(并且不能是子类),枚举也可以使用 switch 语句

  • assert

如果 assert 中的布尔条件为 false,那么正常的程序执行流程会被中断

assert 语句只在开发环境中有效,在生产环境是无效的

异常

​ Dart 可以抛出和捕获异常,如果没有被捕获,则会抛出,最终导致程序终止运行

​ 和 Java 不同,Dart 中的所有异常时非检查异常,方法不会声明它们抛出的异常,也不要求捕获任何异常

​ Dart 提供了 Exception 和 Error 类型,以及一些子类型。也可以自定义异常类型。此外,Dart 程序可以抛出任何 非null 对象,不仅限 Exception 和 Error 对象。

  • throw
代码语言:javascript
复制
throw FormatException('Expected at least 1 section');
  • 抛出任意的对象
代码语言:javascript
复制
void distanceTo(Point other) => throw UnimplementedError();
  • 在使用表达式的地方抛出异常
代码语言:javascript
复制
void distanceTo(Point other) => throw UnimplementedError();
  • Catch

捕获异常

代码语言:javascript
复制
try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 一个特殊的异常
  buyMoreLlamas();
} on Exception catch (e) {
  // 其他任何异常
  print('Unknown exception: $e');
} catch (e) {
  // 没有指定的类型,处理所有异常
  print('Something really unknown: $e');
}

catch 函数可以指定 1到2个参数,第一个为异常对象,第二个为堆栈信息(StackTrace对象)

代码语言:javascript
复制
try {
  // ···
} on Exception catch (e) {
  print('Exception details:\n $e');
} catch (e, s) {
  print('Exception details:\n $e');
  print('Stack trace:\n $s');
}

如果部分异常需要处理,可使用 rethrow 将异常重新抛出

代码语言:javascript
复制
void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // Runtime error
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // Allow callers to see the exception.
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}
  • finally

无论是否 try 住异常,finally 都会执行。如果 try 住异常,会先执行对应的 catch,最后执行 finally

​ Dart 是一种基于类和 mixin 继承机制的面向对象的语言,每个对象都是一个类的实例,所有的类都继承于 Object. 。 基于 Mixin 继承 意味着每个类(除 Object 外) 都只有一个超类, 一个类中的代码可以在其他多个继承类中重复使用。

  • 创建对象
代码语言:javascript
复制
var p = Point(2, 2);

// 为实例的变量 y 设置值。
p.y = 3;

// 获取变量 y 的值。
assert(p.y == 3);

//如果 p 非空,则设置y=8
p?.y = 8

// 调用 p 的 distanceTo() 方法。
num distance = p.distanceTo(Point(4, 4));

使用 ?. 来代替 . , 可以避免因为左边对象可能为 null , 导致的异常

  • 获取对象类型

使用对象的 runtimeType 属性, 可以在运行时获取对象的类型, runtimeType 属性回返回一个 Type 对象。

  • 实例变量
代码语言:javascript
复制
class Point {
  num x; // 声明示例变量 x,初始值为 null 。
  num y; // 声明示例变量 y,初始值为 null 。
  num z = 0; // 声明示例变量 z,初始值为 0 。
}

未初始化的变量为 null

所有实例变量都隐式生成 getter 方法,非 final 的变量会生成 setter 方法

  • 默认构造

没有声明构造时,Dart 会提供一个默认的构造

  • 构造函数不被继承

子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数 (匿名,没有参数) 。

  • 命名构造函数

使用命名构造函数可以为一个类实现多个构造函数,也可以使用命名构造函数来更清晰的表明函数意图:

代码语言:javascript
复制
class Point {
  num x, y;

  Point(this.x, this.y);

  // 命名构造函数
  Point.origin() {
    x = 0;
    y = 0;
  }
}

切记,构造函数不能够被继承, 这意味着父类的命名构造函数不会被子类继承。 如果希望使用父类中定义的命名构造函数创建子类, 就必须在子类中实现该构造函数。

  • 调用父类field默认构造函数

执行顺序如下:

  1. initializer list (初始化参数列表)
  2. superclass’s no-arg constructor (父类的无名构造函数)
  3. main class’s no-arg constructor (主类的无名构造函数)
代码语言:javascript
复制
class Person {
  String firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}

main() {
  var emp = new Employee.fromJson({});

  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
  }
  (emp as Person).firstName = 'Bob';
}
  • 常量构造函数

如果你的类,创建的对象永远也不会改变,你可以在编译期就创建这个常量实例,并定义常量构造函数,并且确保所有的成员变量都是 final 的。

代码语言:javascript
复制
var p = const ImmutablePoint(2, 2);

在构造函数名之前加 const 关机字,来创建编译时常量

注意:构造两个相同编译时常量会产生一个相同的实例

在常量上下文中,const 可以被省略:

代码语言:javascript
复制
// 这里有很多的 const 关键字。
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
代码语言:javascript
复制
  // 仅有一个 const ,由该 const 建立常量上下文。
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

在 Dart2中,一个常量上下文中的 const 关键字可以被省略

代码语言:javascript
复制
class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final num x, y;

  const ImmutablePoint(this.x, this.y);
}
  • 工厂构造函数
代码语言:javascript
复制
class Logger {
  final String name;
  bool mute = false;

  // 从命名的 _ 可以知,
  // _cache 是私有属性。
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}

其实就是一个工厂模式,传如对于的 name,然后获取到对应的实例

  • 关于其他的

抽象类,枚举,这些就不详细的说了,都是基本操作,和java差不多。如果不懂,可自行到官网查看

异步操作

  • Future
代码语言:javascript
复制
void main() {
  print("start ----------->");
  print(getNetData());
  print("end -------------->");
}

String getNetData() {
  //耗时 3 秒
  sleep(Duration(seconds: 3));
  return "网络数据";
}
代码语言:javascript
复制
start ----------->F
//耗时三秒,打印如下
网络数据
end -------------->

可以看到,main 方法直接被阻塞了,导致接下来的代码无法继续执行,这种肯定是由问题的

异步网络请求

代码语言:javascript
复制
Future<String> getNetData() {
  return Future(() {
    sleep(Duration(seconds: 3));
    return "网络数据";
  });
}
代码语言:javascript
复制
start ----------->
Instance of 'Future<String>'
end -------------->

使用 future 对象将耗时操作放在了传入参数的函数中

可以看到没有发生阻塞,但是返回的结果却是 future 的实例。通过 future 就可以将耗时操作隔离,不会影响的主线程的执行。

获取 future 的结果

代码语言:javascript
复制
//getNetData 返回的 future 有返回结果时,就会自动调用 then 中传入的函数
//该函数会被放在事件循环中,被执行
getNetData().then((value) {
  print(value);
});
代码语言:javascript
复制
start ----------->
end -------------->
网络数据

执行过程中的异常

代码语言:javascript
复制
getNetData().then((value) {
  //支持成功到此处
  print(value);
}).catchError((error) {
  //执行失败到此处
  print(error);
});

常用的方法

  • Future.whenComplete

无论执行成功或者失败都会走到这里

代码语言:javascript
复制
getNetData().then((value) {
  //支持成功到此处
  print(value);
}).catchError((error) {
  //执行失败到此处
  print(error);
}).whenComplete(() => print("完成"));

可以用来做一些关闭对话框等操作

  • Future.them 链式调用
代码语言:javascript
复制
//在 them 中可以接继续返回值,该值会在下一个链式的 then 调用中拿到返回的结果
getNetData().then((value) {
  //支持成功到此处
  print(value);
  return "data1";
}).then((value) {
  print(value);
  return "data2";
}).then((value) {
  print(value);
}).catchError((error) {
  //执行失败到此处
  print(error);
}).whenComplete(() => print("完成"));
代码语言:javascript
复制
网络数据
data1
data2
完成
  • Future.wait

如果要等到多个异步任务都结束之后再进行一些操作,可以使用 Future.wait

代码语言:javascript
复制
Future.wait([getNetData(), getNetData(), getNetData()]).then((value) {
  value.forEach((element) {
    print(element);
  });
});

wait 接受一个 future 类型的数组,当 数组的 future 都执行成功后才会执行 then

  • Future.delayed

延时一定的时间后在执行函数

代码语言:javascript
复制
 Future.delayed(Duration(seconds: 3), () {
    return "3秒后的信息";
  }).then((value) {
    print(value);
  });
  • async,await

async:用来表示函数时异步的,定义的函数会返回一个 Future 对象,可以使用 then 添加回调函数

await :后面是一个 Future,表示等待改异步任务的完成,异步完成之后才会继续往下走,await 必须出现在 async 的内部

代码语言:javascript
复制
void main() {
  print("start ------
  ----->");

  getNetData().then((value) => print(value));

  print("end -------------->");
}

Future<String> getNetData() async {
  var result1 = await Future.delayed(Duration(seconds: 3), () {
    return "网络数据1";
  });
  var result2 = await Future.delayed(Duration(seconds: 3), () {
    return "网络数据2";
  });
  return result1 + "-----" + result2;
}
代码语言:javascript
复制
在 getNetData 中,拿到两个结果进行拼接,然后一起返回
  
  返回值会被包装在一个 Futter 中,在调用处就可以使用 them 直接拿到结果

---

> 参考文献:官方文档,Flutter实战,[Dart 异步](https://juejin.cn/post/6844903942795558919#heading-11)



## 下面让我们一起

> happy codeing
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/10/29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一个简单的 Dart 程序
  • 重要的概念
  • 关键字
  • 变量
  • 默认值
  • Final 和 Const
  • 内建类型
  • Null-aware
  • 函数
  • 扩展函数,属性
  • 运算符
  • 控制流程语句
  • 异常
  • 异步操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档