检查一下你的Flutter项目里有多少这样的代码
if(xxx != null && xxx.isNotEmpty)
不得不说,我真的不喜欢这种先想条件,然后再想着在外面包一层 if
这种逆着思维顺序的代码方式(毕竟大家都活在「TENET」的世界里😏),尤其 if 里的条件比较长的时候。
消灭 == null
众所周知,dart 里有 ?.
和 ??
这种判空操作符,于是上面的代码可以简化成这样:
String a = "dart";
if (a?.isNotEmpty ?? false) {
print('😏');
}
但是还是好麻烦呐
封装一个扩展函数试试
给常用的类型添加 isNullOrEmpty
扩展函数
extension MapExtension on Map {
bool get isNullOrEmpty => (this == null || this.isEmpty);
}
extension IterableExtension on Iterable {
bool get isNullOrEmpty => (this == null || this.isEmpty);
}
extension StringExtension on String {
bool get isNullOrEmpty => (this == null || this.isEmpty);
}
好了现在我们可以这样写:
String a = null;
if (!a.isNullOrEmpty) {
print("😒");
} else print("Shit");
但是还有一种场景是不处理 null 的分支,只处理 empty or notEmpty
把 Kotlin 的方案搬过来,对bool类型加扩展函数
先写用法:
String a = "";
a?.isEmpty?.yes(() {
print("Yes!");
})?.orElse(() {
print("No! God No!");
})
如果你还是想要判断空分支,那还可以在后面加上??
看起来没有 kotlin 那么美观,但是至少不用写 if 了,代码实现在下面👇
class BooleanExt<T extends Object> {
T orElse(T block()) {
if (this is OrElse) {
return block() ?? Null;
} else {
return (this as WithData).data ?? Null;
}
}
}
class OrElse extends BooleanExt<Object> {}
class WithData<T> extends BooleanExt<T> {
final T data;
WithData(this.data);
}
extension BoolExtension<T> on bool {
BooleanExt yes(T block()) {
if (this) {
return WithData(block());
} else {
return OrElse();
}
}
BooleanExt no(T block()) {
if (this) {
return OrElse();
} else {
return WithData(block());
}
}
}
以上代码都基于现在稳定版的语法,不过前段时间 Dart 发布了一个实验特性,加入了空安全的完整版
新版 Dart 的「空安全」
新的空安全机制改得和 Kotlin 一样了,直接分成「可空」和「不可空」两大类型,一个变量允许赋值为null
就必须提前声明为不可空类型,各位可以在 https://nullsafety.dartpad.cn/ 这里玩一下。
在新版空安全下,上面的 isNullorEmpty
的实现和调用得改成这样:
extension IterableExtension on Iterable? {
bool get isNullOrEmpty => (this == null || this!.isEmpty);
}
///
List<String>? a = null;
if (a.isNullOrEmpty) {
print("DOG");
} else {
print("Cat");
}
emmm,可以发现这个语言还是不太聪明的样子,我明明前面都写了 this == null ||
, 后面调用还是要加上 !
操作符强制认定不为空,在 Kotlin 里,这里就可以智能判断,Kotlin 真香🌝。
总结
Dart 虽然开始的时候比较简陋,但是一直在进步,有了扩展函数,有了严格的空安全,下一步是不是可以考虑支持 DSL 语法了😏