Dart的空值判断
Dart语言已经提供了很多语法糖来改善判断空值的写法,但是还是有两种情况不容易判断:
判断function
是否为空
此时需要这样往往需要这样写代码:
问题代码
Function(String) filter;
// 一定要写一个if,其实很不优雅
if(filter != null){
filter('some string');
}
解决方案:使用?.call()
调用
Function(String) filter;
// 一行判断function是否为空,并执行function
filter?.call('some string');
对Map连续取值时,在过程中报错,无法安全取值
例如有Map如下:
Map map = {
'id': 3,
'tag': 'user',
'info': {
'name': 'Jerry',
//'age': 5,
}
};
如果取值就很容易报错:
问题代码
map['info']; // 取出map
map['info']['name']; // 取出'Jerry'
map['info2']['remark']; // 取不存在的key,再取值就回报错
// 我在项目中的代码,查询Accu的天气详情,这样会非常不稳定
source['Wind']['Speed']['Metric']['Value']
因为有时调用的Api并不完全可靠,我们当然不希望云端的json结构变化就直接导致我们整个程序报错。如果堆叠很多个if判断,会让程序难以阅读。
Tips:javascript
中可以使用map?.['info']
进行取值。
解决方案:封装SafeMap类,使其可以一直取值
思路很简单,重载[]
操作符即可
完整代码:GitHub仓库地址
class SafeMap {
SafeMap(this.value);
final dynamic value;
SafeMap operator [](dynamic key) {
if (value is Map) return SafeMap(value[key]);
if (value is List) {
List _list = value;
int max = _list.length - 1;
if (key is int && key < max) return SafeMap(value[key]);
}
return SafeMap(null);
}
dynamic get v => value;
String get string => value is String ? value as String : null;
num get number => value is num ? value as num : null;
Map get map => value is Map ? value as Map : null;
List get list => value is List ? value as List : null;
bool get boolean => value is bool ? value as bool : false;
bool isEmpty() {
if (this.v == null) return true;
if (this.string == '') return true;
if (this.number == 0) return true;
if (this.map?.keys?.length == 0) return true;
if (this.list?.length == 0) return true;
if (this.boolean == false) return true;
return false;
}
@override
String toString() => '<SafeMap:$value>';
}
使用:
void main() {
test('get value from safemap', () {
// source map
Map map = {
'id': 3,
'tag': 'student',
'info': {
'name': 'Jerry',
},
'class': [
{
"name": 'class 1',
'tag': '',
},
{},
],
};
SafeMap safeMap = SafeMap(map);
// 取值,错误的类型会返回SafeMap(null)
assert(safeMap['id'].value == 3);
assert(safeMap['id'].string == null);
// 错误的下标也会返回SafeMap(null)
assert(safeMap['tag'].value == 'student');
assert(safeMap['tag12345'].value == null);
// 连续取值,可以一直安全取值,只会返回SafeMap(null).
assert(safeMap['info']['name'].value == 'Jerry');
assert(safeMap['a']['b']['b']['b']['b']['b'].value == null);
// 取出数组,也可以通过数组下标继续取值
assert(safeMap['class'].list.length == 2);
assert(safeMap['class'][0]['name'].value == 'class 1');
// {},[],0,'',null 都会被判断为空
assert(safeMap['class'][0]['tag'].isEmpty());
assert(safeMap['class'][1].isEmpty());
// 越界也会返回SafeMap(null),判断isEmpty为true
assert(safeMap['class'][2].isEmpty());
});
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。