dart 学习 之 字符串插值,空变量 null,避空运算符,条件属性访问,集合字面量,箭头语法

字符串插值(String interpolation)

下面是一些使用字符串插值的例子:
Here are some examples of using string interpolation:

String     									result
字符串 										结果
'${3 + 2}'	 	  							 '5'
'${"word".toUpperCase()}'	 				'WORD'
The value of '$myObject' 					myObject.toString().

小练习:
Q: 下面的方法接收两个整型变量作为参数,然后让它返回一个包含以空格分隔的整数的字符串。例如,stringify(2, 3) 应该返回 ‘2 3’。
A:

String stringify(int x, int y) {
  return '${x} ${y}'
}

或者
String stringify(int x, int y) {
return ‘KaTeX parse error: Double superscript at position 10: {x}' + ' '̲ + '{y}’;
}

空变量 null

Dart 要求使用健全的空安全,这意味着除非变量显式声明为可空类型,否则它们将不能为空。换句话说,类型默认是不可为空的。
举个例子,下面的代码在空安全下是有错误的,因为 int 类型的变量不能为 null:

int a = null; // INVALID.

你可以通过在类型后添加 ? 来表示该类型可空:

int? a = null; // Valid.

在所有 Dart 版本中,null 在未初始化的变量里都是默认值,所以你可以这样简化你的代码:

int? a; // The initial value of a is null.

Q:
试着定义以下两种变量:

一个可空的 String,名为 name,值为 ‘Jane’。

一个可空的 String,名为 address,值为 null。

A:

String ?name = 'Jane';
String ?address ;

避空运算符

Dart 提供了一系列方便的运算符用于处理可能会为空值的变量。其中一个是 ??= 赋值运算符,仅当该变量为空值时才为其赋值:

int? a; // = null
a ??= 3;
print(a); // <-- Prints 3.

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

另外一个避空运算符是 ??,如果该运算符左边的表达式返回的是空值,则会计算并返回右边的表达式。

print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.
String? baz = foo ?? bar; // 如果 foo 是 null 才会赋值为 bar

条件属性访问

要保护可能会为空的属性的正常访问,请在点(.)之前加一个问号(?)。

myObject?.someProperty

上述代码等效于以下内容:

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

你可以在一个表达式中连续使用多个 ?.:

myObject?.someProperty?.someMethod()

如果 myObject 或 myObject.someProperty 为空,则前面的代码返回 null(并不再调用 someMethod)。

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

// This method should return the uppercase version of `str`
// or null if `str` is null.
String? upperCaseIt(String? str) {
  // Try conditionally accessing the `toUpperCase` method here.
  
}

A:

return str?.toUpperCase()  ;  // 如果不为空就返回大写字母

集合字面量

Dart 内置了对 list、map 以及 set 的支持。你可以通过字面量直接创建它们:

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

Dart 的类型推断可以自动帮你分配这些变量的类型。在这个例子中,推断类型是 List、Set和 Map<String, int>。

你也可以手动指定类型:

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

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

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

Q:
尝试将以下变量设定为指定的值。替换当前的 null 值。

// Assign this a list containing 'a', 'b', and 'c' in that order:
final aListOfStrings =null ;

// Assign this a set containing 3, 4, and 5:
final aSetOfInts = null;

// Assign this a map of String to int so that aMapOfStringsToInts['myKey'] returns 12:
final aMapOfStringsToInts = null;

// Assign this an empty List<double>:
final anEmptyListOfDouble = null;

// Assign this an empty Set<String>:
final anEmptySetOfString = null;

// Assign this an empty Map of double to int:
final anEmptyMapOfDoublesToInts = null;

A:

// Assign this a list containing 'a', 'b', and 'c' in that order:
final aListOfStrings = ['a', 'b', 'c'];

// Assign this a set containing 3, 4, and 5:
final aSetOfInts = {3, 4, 5};

// Assign this a map of String to int so that aMapOfStringsToInts['myKey'] returns 12:
final aMapOfStringsToInts = {'myKey': 12};

// Assign this an empty List<double>:
final anEmptyListOfDouble = <double>[];

// Assign this an empty Set<String>:
final anEmptySetOfString = <String>{};

// Assign this an empty Map of double to int:
final anEmptyMapOfDoublesToInts = <double, int>{};

箭头语法

你也许已经在 Dart 代码中见到过 => 符号。这种箭头语法是一种定义函数的方法,该函数将在其右侧执行表达式并返回其值。

例如,考虑调用这个 List 类中的 any 方法:

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

这里是一个更简单的代码实现:

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

看看下面的代码

class MyClass {
  int value1 = 2;
  int value2 = 3;
  int value3 = 5;

  // Returns the product of the above values:
  int get product => value1 * value2 * value3;
  
  // Adds 1 to value1:
  void incrementValue1() => value1++; 
  
  // Returns a string containing each item in the
  // list, separated by commas (e.g. 'a,b,c'): 
  String joinWithCommas(List<String> strings) => strings.join(',');
}