extension 作为 dart 中重要的关键字之一, 主要用于扩展函数方法

我们在实际开发过程中, 可能会或多或少遇到一些问题. 例如在 List 数组中, 现在只提供了 List.first 的方法. 我们想去获取数组中第二个对象, 比方说 second 方法, 这个方法就没有. 这个时候往往大家会通过创建新方法的方式去获取数组中第二个对象.

1
2
3
4
dynamic getSecond(List list) {
if (list.length < 2) return null;
return list[1];
}

这个方式的好处在于简单明了, 但是我们在开发过程中, 往往过程是不可预料的, 可能会写很多重复且丑陋都代码. 有没有一种方法, 在不修改源码为前提下, 可以基于原来的类作扩展呢? 答案就是 Extension .

用法

我们可以通过 extensoin 关键字创建扩展方法, 并且通过 on 关键字指定在类中. 在使用的时候, 我们只需要把相应的 extension 引入包内即可调用相关方法. 以下我们通过几个示例来看看 extension 的作用:

扩展基本类型

基本类型如 num 、string 、bool 之类的, 我们以 String 为例.

1
2
3
4
5
6
7
8
9
10
11
extension BoolEx on String {
// 判断当前的String是否包含空格
bool get isContainsBlank {
return contains(' ');
}
}

void main() {
print('hello juejin ${'hello juejin'.isContainsBlank}');
print('helloJuejin ${'helloJuejin'.isContainsBlank}');
}

结果如图:

result
我们通过 extension 构建了一个 isContainsBlank 的 get 方法, 通过这个方法, 我们隐式的调用了 String 中的 contains 方法来判断当前字符中是否包含空白字符.结果也确实如我们所料, 在包含空格的“ hello juejin”中输出了true.

扩展类

实际上, 任何一个类我们都可以通过扩展函数来扩展. 我们以 Colors 为例, 我们可以通过扩展函数来显式的生成一个半透明的颜色:

1
2
3
4
5
extension ColorEx on Color {
Color get translucent {
return withOpacity(0.5);
}
}

通过 translucent 方法, 我们可以根据现在的颜色返回一个新的透明度为50% 的新颜色.在实际开发过程中, 我们也可以通过 extension 方法, 去扩展三方api、不方便修改源码的类等等.以此用最小的代价完成开发.

扩展Widget

widget 实际上也是一个类, 那么能扩展类, 自然也就可以扩展 Widget. 如果你们的团队有一套设计规范.每个 widget 需要一套固定的 Padding 或者其他设计. 可以参考这种方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
extension WidgetEx on Widget {
// 比如说我们需要在每个widget外加上一个固定的 Padding
Widget get addPadding {
return Padding(
padding: const EdgeInsets.all(10.0),
child: this,
);
}
}

// 我们可以直接通过addPadding方法给它加一个外边距
return Container(
child: Row(),
).addPadding;

通过扩展 Widget 增加一个 addPadding 的方法, 我们最终在原 widget 上增加了 Padding. 通过这种形式, 可以最大程度的减少开发工作量, 统一设计规范.

扩展枚举

相对来说, 笔者用这部分类型会更多一些. 与魔数、flag对比, 枚举会更好维护, 也能更好的表达意思. 但是通常枚举只能作为一个类别的标识, 这里我们就可以通过扩展函数去扩展枚举, 给枚举值赋予更多的含义.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enum FileType {
image,
text,
video,
}

extension FileTypeEx on FileType {
String get name {
Map<FileType, String> params = {
FileType.text: '文本',
FileType.image: '图片',
FileType.video: '视频',
};
return params[this]!;
}

bool get isImage {
return this == FileType.image;
}
}

在这个例子中, 我们生成了一个文件分类的枚举. 如果只是枚举, 往往只能作为文件类别的区分. 这里我们通过扩展函数, 赋予它 name 以及IsImage 方法, 可以直接获取该类别下的名称. 或者直接判断该类别是否为图片. 我们还可以通过扩展函数增加这一类别的路径等等. 简单来说, 通过扩展函数可以更便捷等协助我们开发. 精简化我们的代码.


!
!
!

不过切记也不要乱用, 尽量是抽出通用的方法来扩展. 否则后期逻辑更难维护!

结语

这里是WeninerIo,如果你对这次的技术分享感兴趣或者有什么疑惑, 不妨在评论区留言或私信.
或许这次的分享不是你期待的点, 那就点个关注吧! 下次也许就是适合你的点呢?

Thanks for meeting ! ! !

image