Dart3 if-case-when的一些奇妙用法

昨天看群友发了一张这样代码图: 里面有两点让我感到很疑惑:AsyncData(:final value)是什么东西?if (value.data?.topics case final topic?)又是个啥?这真的还是dart代码吗? 于是上网一查,原来还真有这样的东西,该更新一下大脑补一下课了。

if-case-when

上面的是官方的解释,嗯...我们还是自己动手试试吧。

在以前,如果判断一个值是否为数组且该数组长度为2且该数组里的元素都大于0,可以这样写:

javascript 复制代码
void checkTypeOld(dynamic value) {
  if (value is List && value.length == 2 && value.every((e) => e > 0)) {
    print('value.type is list and value.length == 2 and all element of value is bigger than 0');
  }
}

用dart3则可以这样:

csharp 复制代码
void checkTypeNew(dynamic value) {
  if (value case [int x, int y] when x > 0 && y > 0) {
    print('value.type is list and value.length == 2 and all element of value is bigger than 0');
  }
}

看起来dart3更简洁?它一句case [int x, int y]就做了前两个判断同时取值出来方便下一步计算。

那么能不能再更简洁一点呢?假设这里要判断的长度不是2,而是20,[int x, int y...]这样赋值也太累了。答案当然是可以的。

csharp 复制代码
void checkTypeNew(dynamic value) {
  if (value case List(length: 20) when value.every((e) => e > 0)) {
    print('value.type is list and value.length == 20 and all element of value is bigger than 0');
  }
}

List()能用的不仅有length,还有isEmptyfirst等,只要类型里有写getter方法的都能用。

AsyncData(:final value)

AsyncData是riverpod自定义的class,继承于AsyncValue。通过观察上述的代码能够判断出hotList应该是一个AsyncValue类型的变量,然后在这里通过switch判断具体的类型来显示不同的UI。明白了代码的作用后就该看看那个:final value是啥了。

这里我跟着riverpod的教程弄了一下,其中Activity是自定义的类,里面只有一个final String key

scss 复制代码
Consumer(
  builder: (context, ref, child) {
    final AsyncValue<Activity> activity = ref.watch(activityProvider);
    return Center(
      child: switch (activity) {
        AsyncData(:Activity value) => Text('Activity: ${value.key}'),
        AsyncError() => const Text('Oops, something unexpected happened'),
        _ => const CircularProgressIndicator(),
      },
    );
  },
);

这样就可以明确看出activityvalue的类型,那么根据AsyncData的源码,不难看出:Activity value就是取出AsyncData里的值的意思。

那么如果我不喜欢value,可以把它改成item或者其他的变量吗?

并不可以!会报出以下错误The getter 'item' isn't defined for the type 'AsyncData<Activity>'.

又是getter!再深入进去看一眼AsyncValue的实现,发现它其实是这样的:

综上所述,如果想要使用:final value这种语法,也是要求类有提供getter方法。那么我自己也实现一个试试。

dart 复制代码
class Item {
  Item._(this._id);

  factory Item.from(String id) => Item._(id);

  String _id;

  String get id => _id;

  set id(String value) {
    if (value != id) {
      _id = value;
    }
  }
}

把它也加到上面判断类型的函数里那就会是这样:

csharp 复制代码
void checkTypeNew(dynamic value) {
  if (value case List(length: 20) when value.every((e) => e > 0)) {
    print('value.type is list and value.length == 20 and all element of value is bigger than 0');
  } else if (value case Item(:final id) when id.isNotEmpty) {
    print('value.type is Item and value.id is not empty');
  }
}

再把这堆if-else优化一下:

scss 复制代码
void checkTypeNew(dynamic value) {
  switch(value) {
    case List(length: 20) when value.every((e) => e > 0):
      print('value.type is list and value.length == 20 and all element of value is bigger than 0');
    case Item(:final id) when id.isNotEmpty:
      print('value.type is Item and value.id is not empty');
  }
}

当然也可以这样写,连case都省略掉:

dart 复制代码
String checkTypeNew(dynamic value) {
  return switch (value) {
    List(length: 20) when value.every((e) => e > 0) =>
      'value.type is list and value.length == 20 and all element of value is bigger than 0',
    Item(:final id) when id.isNotEmpty =>
      'value.type is Item and value.id is not empty',
    _ => 'undefined'
  };
}

// 这样调用
print(checkTypeNew(***));

同时,括号里不仅可以获取一个getter,而是可以获取多个getter,以list为例:

vbnet 复制代码
String checkTypeNew(dynamic value) {
  return switch (value) {
    List(length: 20, :final last)
        when value.every((e) => e > 0) && last > 10 =>
      'value.type is list and value.length == 20 and all element of value > 0 and last element > 10',
    Item(:final id) when id.isNotEmpty =>
      'value.type is Item and value.id is not empty',
    String string when string.isNotEmpty =>
      'value is String and value is not empty',
    _ => 'undefined'
  };
}

最后

这篇文章也只是一个抛砖引玉,我只知道这些东西该怎么用,并不知道这些东西的原理,只能感觉这些都是dart3改新swtich的时候改出来的新特性,具体原理要是能有高手补充一下原理就好了。 dart3这套新switch总是可以把代码写得更简洁,还蛮好用的,虽然不用也没问题,但是你都用flutter这种新玩意了,与时俱进学点新东西不是挺好的吗?

相关推荐
幸福专买店1 天前
【Flutter】flutter 中 包裹内容显示 的设置方式
前端·javascript·flutter
QuantumLeap丶1 天前
《Flutter全栈开发实战指南:从零到高级》- 17 -核心动画
android·flutter·ios
小恒恒1 天前
Flutter 3.32.1 开发环境搭建
flutter
吴Wu涛涛涛涛涛Tao1 天前
用 Flutter + BLoC 写一个顺手的涂鸦画板(支持撤销 / 重做 / 橡皮擦 / 保存相册)
android·flutter·ios
一名普通的程序员1 天前
在 Flutter + GetX 中实现 Design Tokens 的完整方案
flutter
轮孑哥1 天前
flutter flutter_distributor打包错误
windows·flutter
肠胃炎1 天前
Flutter 线性组件详解
前端·flutter
肠胃炎1 天前
Flutter 布局组件详解
前端·flutter
不爱吃糖的程序媛1 天前
彻底解决 Flutter 开发 HarmonyOS 应用:No Hmos SDK found 报错
flutter·华为·harmonyos
liuxf12341 天前
fvm管理鸿蒙flutter
flutter·华为·harmonyos