首页 > 解决方案 > 飞镖 | Flutter:如何在 null 安全下从 Map 传递函数?为什么需要 bang 运算符?

问题描述

背景:

我一直在研究如何使用 dart 代码使用 Map 传递函数。然而,我现在很难过。在使用空安全时使用 DartPad 时,我从以下代码中得到了一个意外的空值:

void main() {
Map<String, Function> fruits = Map();
  fruits['apple'] = appleDescription;
  fruits['banana'] = bananaDescription;
  fruits['grape'] = grapeDescription;
  
  exec(fruits['grape']!);
}

void appleDescription() => print('This fruit tastes like red!');
void bananaDescription() => print('This fruit tastes like yellow!');
void grapeDescription() => print('This fruit tastes like purple!');

void exec(Function f) {
    print(f());
}

DartPad 控制台如下图所示:

代码运行后 DartPad 截图

问题:

我认为答案很容易,但我已经为此苦苦挣扎了一段时间。我的问题是:

  1. 我只希望,“这种水果尝起来像紫色!” 已在控制台中打印,所以我必须在这里遗漏一些东西。我是从地图中正确传递这个函数,还是有一种更安全的传递方式?

  2. 我想知道为什么在调用 exec() 函数时必须使用 bang 运算符。由于我已经定义了 fruits 映射包含 <String, Function>,编译器会理解它必须存在。我错过了什么?

再次,提前感谢您的任何建议,我们非常感谢社区接受。

更新:

我使用以下代码删除了 bang 运算符,并在下面的答案中给出了更正:

void main() {
Map<String, Function> fruits = Map();
  fruits['apple'] = appleDescription;
  fruits['banana'] = bananaDescription;
  fruits['cranberry'] = grapeDescription;
  
  exec(fruits['cranberry']??= (){print('');});
}

void appleDescription() => print('This fruit tastes like red!');
void bananaDescription() => print('This fruit tastes like yellow!');
void grapeDescription() => print('This fruit tastes like purple!');

void exec(Function f) {
    f();
}

标签: dartdart-null-safety

解决方案


您的exec函数尝试打印函数的结果,该f()函数本身会打印您正在等待的短语。

所以基本上:

  1. 代码输入exec
  2. 来电f()
  3. f()打印This fruit tastes like purple!并返回void
  4. 打印返回值的print方法=> nullexec

总而言之,您正在打印print函数的返回值。

为了使您的代码按预期运行,您应该使用

void exec(Function f) {
    f();
}

要回答您的第二个问题,如果您没有将现有密钥传递给它,则Map可以返回。null这就是你应该使用 bang 的原因,因为Map不能保证返回的值是非 null 的。


推荐阅读