Contents

Dart cheatsheet codelab

Dart语言旨在让其他语言的编码人员易于学习,但是它具有一些独特的功能. 该代码实验室-基于由Google工程师编写并为Google工程师编写的Dart语言速查表 -引导您完成这些语言功能中最重要的部分.

该代码实验室中的嵌入式编辑器具有部分完成的代码段. 您可以使用这些编辑器通过完成代码并单击" 运行"按钮来测试您的知识. 如果需要帮助,请单击" 提示"按钮. 要运行代码格式化程序( dartfmt ),请点击格式 . " 重置"按钮将删除您的工作并将编辑器恢复到其原始状态.

String interpolation

要将表达式的值放在字符串中,请使用${expression} . 如果表达式是标识符,则可以省略{} .

以下是一些使用字符串插值的示例:

String   Result
'${3 + 2}'   '5'
'${"word".toUpperCase()}'   'WORD'
'$myObject'   myObject.toString()的值

Code example

以下函数将两个整数作为参数. 使它返回一个字符串,该字符串包含两个用空格分隔的整数. 例如, stringify(2, 3)应该返回'2 3' .

Null-aware operators

Dart提供了一些方便的运算符来处理可能为null的值. 一个是??=赋值运算符,它仅在该变量当前为null时才为该变量赋值:

int a; // The initial value of a is null.
a ??= 3;
print(a); // <-- Prints 3.

a ??= 5;
print(a); // <-- Still prints 3.

另一个空值运算符是?? ,除非该表达式的值为null,否则它将在其左侧返回该表达式,在这种情况下,它将求值并在其右侧返回该表达式:

print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.

Code example

尝试放置??=?? 操作员要在下面工作.

Conditional property access

为了保护对可能为空的对象的属性或方法的访问,请在点( . )前面打一个问号( ? ):

myObject?.someProperty

上面的代码等效于以下代码:

(myObject != null) ? myObject.someProperty : null

您可以连锁使用?. 一起在一个表达式中:

myObject?.someProperty?.someMethod()

如果myObjectmyObject.someProperty为null,则前面的代码返回null(并且从不调用someMethod() ).

Code example

尝试使用条件属性访问来完成下面的代码片段.

Collection literals

Dart具有对列表,地图和集合的内置支持. 您可以使用文字创建它们:

final aListOfStrings = ['one', 'two', 'three'];
final aSetOfStrings = {'one', 'two', 'three'};
final aMapOfStringsToInts = {
  'one': 1,
  'two': 2,
  'three': 3,
};

Dart的类型推断可以为您为这些变量分配类型. 在这种情况下,推断的类型为List<String>Set<String>Map<String, int> .

或者您可以自己指定类型:

final aListOfInts = <int>[];
final aSetOfInts = <int>{};
final aMapOfIntToDouble = <int, double>{};

当使用子类型的内容初始化列表,但仍希望列表为List<BaseType>时,指定类型很方便:

final aListOfBaseType = <BaseType>[SubType(), SubType()];

Code example

尝试将以下变量设置为指示的值.

Arrow syntax

您可能已经在Dart代码中看到了=>符号. 此箭头语法是一种定义函数的方法,该函数将在其右侧执行表达式并返回其值.

例如,考虑对List类的any()方法的此调用:

bool hasEmpty = aListOfStrings.any((s) {
  return s.isEmpty;
});

这是编写该代码的一种更简单的方法:

bool hasEmpty = aListOfStrings.any((s) => s.isEmpty);

Code example

尝试完成以下使用箭头语法的语句.

Cascades

要对同一对象执行一系列操作,请使用级联( .. ). 我们都看到过这样的表达式:

myObject.someMethod()

它在myObject上调用someMethod() ,表达式的结果是someMethod()的返回值.

这是带有级联的相同表达式:

myObject..someMethod()

尽管它仍然在myObject上调用someMethod() ,但表达式的结果不是返回值,而是对myObject的引用! 使用级联,可以将原本需要单独语句的操作链接在一起. 例如,考虑以下代码:

var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

使用层叠时,代码变得更短,并且您不需要button变量:

querySelector('#confirm')
..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));

Code example

使用级联,以创建单个语句套anIntaStringaList一个属性BigObject1'String!' 以及[3.0] (分别),然后调用allDone() .

Getters and setters

只要您需要对属性的控制超出简单字段允许的范围,就可以定义getter和setter.

例如,您可以确保属性的值有效:

class MyClass {
  int _aProperty = 0;

  int get aProperty => _aProperty;

  set aProperty(int value) {
    if (value >= 0) {
      _aProperty = value;
    }
  }
}

您还可以使用getter来定义计算属性:

class MyClass {
  List<int> _values = [];

  void addValue(int value) {
    _values.add(value);
  }

  // A computed property.
  int get count {
    return _values.length;
  }
}

Code example

假设您有一个购物车类,其中有一个私有的价格List<double> . 添加以下内容:

  • 一个称为total的吸气剂,它返回价格的总和
  • 只要新列表不包含任何负价(在这种情况下,设置者应抛出InvalidPriceException ),就可以用新的列表代替该设置器.

Optional positional parameters

Dart具有两种功能参数:positional和named. 位置参数是您可能熟悉的一种:

int sumUp(int a, int b, int c) {
  return a + b + c;
}

int total = sumUp(1, 2, 3);

使用Dart,您可以将这些位置参数包装在方括号中,以使其成为可选参数:

int sumUpToFive(int a, [int b, int c, int d, int e]) {
  int sum = a;
  if (b != null) sum += b;
  if (c != null) sum += c;
  if (d != null) sum += d;
  if (e != null) sum += e;
  return sum;
}

int total = sumUptoFive(1, 2);
int otherTotal = sumUpToFive(1, 2, 3, 4, 5);

可选的位置参数始终位于函数的参数列表中. 除非您提供另一个默认值,否则它们的默认值为null:

int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) {
  ...
}

int newTotal = sumUpToFive(1);
print(newTotal); // <-- prints 15

Code example

实现一个名为joinWithCommas()的函数,该函数接受joinWithCommas()个整数,然后返回由逗号分隔的那些数字的字符串. 以下是一些函数调用和返回值的示例:

函数调用   返回值
joinWithCommas(1)   '1'
joinWithCommas(1, 2, 3)   '1,2,3'
joinWithCommas(1, 1, 1, 1, 1)   '1,1,1,1,1'


Optional named parameters

使用大括号语法,可以定义具有名称的可选参数.

void printName(String firstName, String lastName, {String suffix}) {
  print('$firstName $lastName ${suffix ?? ''}');
}

printName('Avinash', 'Gupta');
printName('Poshmeister', 'Moneybuckets', suffix: 'IV');

如您所料,这些参数的值默认为null,但是您可以提供默认值:

void printName(String firstName, String lastName, {String suffix = ''}) {
  print('$firstName $lastName ${suffix}');
}

函数不能同时具有可选的位置参数和可选的命名参数.

Code example

将一个copyWith()实例方法添加到MyDataObject类. 它应该带有三个命名参数:

  • int newInt
  • String newString
  • double newDouble

调用时, copyWith()应该基于当前实例返回一个新的MyDataObject ,并将先前参数(如果有)中的数据复制到对象的属性中. 例如,如果newInt不为null,则将其值复制到anInt .

Exceptions

Dart代码可以引发并捕获异常. 与Java相反,Dart的所有异常都是未经检查的异常. 方法不声明它们可能引发哪些异常,并且不需要捕获任何异常.

Dart提供了ExceptionError类型,但是您可以抛出任何非null对象:

throw Exception('Something bad happened.');
throw 'Waaaaaaah!';

处理异常时,请使用tryoncatch关键字:

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // A specific exception
  buyMoreLlamas();
} on Exception catch (e) {
  // Anything else that is an exception
  print('Unknown exception: $e');
} catch (e) {
  // No specified type, handles all
  print('Something really unknown: $e');
}

try关键字的工作方式与大多数其他语言相同. 使用on关键字按类型过滤特定的异常,使用catch关键字获取对异常对象的引用.

如果您不能完全处理该异常,请使用rethrow关键字传播该异常:

try {
  breedMoreLlamas();
} catch (e) {
  print('I was just trying to breed llamas!.');
  rethrow;
}

要执行是否抛出异常的代码,请使用finally

try {
  breedMoreLlamas();
} catch (e) {
   handle exception ...
} finally {
  // Always clean up, even if an exception is thrown.
  cleanLlamaStalls();
}

Code example

在下面实现tryFunction() . 它应该执行不可信的方法,然后执行以下操作:

  • 如果logger.logException untrustworthy()抛出ExceptionWithMessagelogger.logException使用异常类型和消息调用logger.logException (尝试使用oncatch ).
  • 如果logger.logException untrustworthy()抛出Exception ,请使用异常类型调用logger.logException (尝试对此使用on ).
  • 如果untrustworthy()抛出任何其他对象,请不要捕获该异常.
  • 在捕获并处理logger.doneLogging所有内容之后,请调用logger.doneLogging (尝试使用finally ).

Using this in a constructor

Dart提供了一个方便的快捷方式,用于为构造函数中的属性分配值:在声明构造函数时使用this.propertyName

class MyColor {
  int red;
  int green;
  int blue;

  MyColor(this.red, this.green, this.blue);
}

final color = MyColor(80, 80, 128);

该技术也适用于命名参数. 属性名称成为参数的名称:

class MyColor {
  ...

  MyColor({this.red, this.green, this.blue});
}

final color = MyColor(red: 80, green: 80, blue: 80);

对于可选参数,默认值可以按预期运行:

MyColor([this.red = 0, this.green = 0, this.blue = 0]);
// or
MyColor({this.red = 0, this.green = 0, this.blue = 0});

Code example

向使用this. MyClass添加一个单行构造函数this. 语法,用于接收和分配该类的所有三个属性的值.

Initializer lists

有时在实现构造函数时,需要在构造函数主体执行之前进行一些设置. 例如,在构造函数体执行之前,final字段必须具有值. 在初始化器列表中执行此操作,该列表在构造函数的签名及其主体之间:

Point.fromJson(Map<String, num> json)
    : x = json['x'],
      y = json['y'] {
  print('In Point.fromJson(): ($x, $y)');
}

初始化器列表也是放置断言的方便位置,断言仅在开发期间运行:

NonNegativePoint(this.x, this.y)
    : assert(x >= 0),
      assert(y >= 0) {
  print('I just made a NonNegativePoint: ($x, $y)');
}

Code example

完成下面的FirstTwoLetters构造函数. 使用初始化列表将word的前两个字符分配给letterOneLetterTwo属性. 为了增加信誉,请添加assert以捕获少于两个字符的单词.

Named constructors

为了允许类具有多个构造函数,Dart支持命名构造函数:

class Point {
  num x, y;

  Point(this.x, this.y);

  Point.origin() {
    x = 0;
    y = 0;
  }
}

要使用命名构造函数,请使用其全名调用它:

final myPoint = Point.origin();

Code example

为Color类提供一个名为Color.black的构造函数,该函数将所有三个属性设置为零.

Factory constructors

Dart支持工厂构造函数,该构造函数可以返回子类型,甚至可以返回null. 要创建工厂构造函数,请使用factory关键字:

class Square extends Shape {}

class Circle extends Shape {}

class Shape {
  Shape();

  factory Shape.fromTypeName(String typeName) {
    if (typeName == 'square') return Square();
    if (typeName == 'circle') return Circle();

    print('I don\'t recognize $typeName');
    return null;
  }
}

Code example

填写名为IntegerHolder.fromList的工厂构造IntegerHolder.fromList ,使其执行以下操作:

  • 如果列表具有一个值,请使用该值创建一个IntegerSingle .
  • 如果列表有两个值,请按顺序创建一个IntegerDouble值.
  • If the list has three values, create an IntegerTriple with the values in order.
  • 否则,返回null.

Redirecting constructors

有时,构造函数的唯一目的是重定向到同一类中的另一个构造函数. 重定向构造的身体是空的,与构造函数调用一个冒号后出现的( : ).

class Automobile {
  String make;
  String model;
  int mpg;

  // The main constructor for this class.
  Automobile(this.make, this.model, this.mpg);

  // Delegates to the main constructor.
  Automobile.hybrid(String make, String model) : this(make, model, 60);

  // Delegates to a named constructor
  Automobile.fancyHybrid() : this.hybrid('Futurecar', 'Mark 2');
}

Code example

还记得上面的Color类吗? 创建一个名为black的命名构造函数,而不是手动分配属性,而是将其重定向到默认构造函数,并使用零作为参数.

Const constructors

如果您的类产生了永不改变的对象,则可以使这些对象具有编译时常量. 为此,请定义const构造函数,并确保所有实例变量都是最终变量.

class ImmutablePoint {
  const ImmutablePoint(this.x, this.y);

  final int x;
  final int y;

  static const ImmutablePoint origin =
      ImmutablePoint(0, 0);
}

Code example

修改Recipe类,使其实例可以是常量,并创建一个执行以下操作的常量构造函数:

  • 具有三个参数: ingredientscaloriesmilligramsOfSodiummilligramsOfSodium顺序).
  • 使用this. 自动将参数值分配给同名对象属性的语法.
  • 是常量,在构造函数声明的Recipe之前使用const关键字.

What next?

我们希望您喜欢使用该代码实验室来学习或测试您对Dart语言最有趣的功能的了解. 以下是一些有关现在要做什么的建议:

by  ICOPY.SITE