简介:
从2.7及以上的dart版本开始,让人殷切期待的扩展函数来了。当你想扩展别人的函数库或者官方的SDK,如果通过更改api的方式则意味着你需要重建一个代码分支,维护一个分支是相当麻烦的事情, 如果这个时候使用扩展方法将是非常方便的。扩展不仅可以定义方法,还可以定义getter,setter和operator。虽然扩展方法中不能用于用dynamic类型,但却支持更强大的泛型扩展。总有人吐槽flutter开发widget嵌套太深的问题,扩展函数的使用能够让代码的结构变得极为简洁,加上泛型扩展的使用可以使代码链式调用一链到底。
原理:
扩展函数调用起来跟原生方法一样自然,使用起来也非常方便,但是这样的用法会不会带来性能方面的问题呢?其实扩展函数的本质是针对接收者的静态类型进行了解析,即扩展方法是静态解析的,扩展函数的实现非常简单,它没有修改接受者类型的成员,仅仅是通过静态方法来实现的,它们与调用静态函数一样快速。
废话少说,下面以本人开发中的使用的经验举几个例子加以说明。
widget扩展:
extension WidgetExt on Widget {
Widget padding(EdgeInsetsGeometry padding) {
return Padding(
child: this,
padding: padding,
);
}
Material gesture({
GestureTapCallback onTap,
GestureTapCallback onDoubleTap,
GestureLongPressCallback onLongPress,
}) {
return Material(
child: InkWell(
child: this,
onTap: onTap,
onDoubleTap: onDoubleTap,
onLongPress: onLongPress,
),
);
}
}
String扩展:
extension StringExt on String {
double toDouble() {
return double.parse(this);
}
int toInt() {
return int.parse(this);
}
bool isMobile(){
return RegExp(r'^((13[0-9])|(14[5,7,9])|(15[^4])|(18[0-9])|(17[0,1,3,5,6,7,8])|(19)[0-9])\d{8}$').hasMatch(this);
}
}
Object扩展:
extension ObjectExt on Object {
bool isNullOrEmpty() {
if (this is String)
return (this as String).isEmpty;
else if (this is Iterable) return (this as Iterable).isEmpty;
return this == null;
}
}
bool扩展:
extension BoolExt on bool {
bool not() {
return !this;
}
bool and(bool val) {
return this && val;
}
bool or(bool val) {
return this || val;
}
}
泛型扩展:
extension AllExt<T> on T {
T apply(f(T e)) {
f(this);
return this;
}
R let<R>(R f(T e)) {
return f(this);
}
}
调用示例如下:仅简单举几个调用例子,其余的调用有兴趣者自行尝试。
实现单层没有嵌的padding和点击事件
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
)
.padding(EdgeInsets.all(10))
.gesture(onTap: () {
}),
],
),
),
实现String正则的判断
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'13646176072'.isMobile()?"手机号":"不是手机号",
),
],
),
),
bool类型的链式调用
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
['13646176072', "fgdgdfgdf", 'trtreter']
.isNullOrEmpty()
.not()
.and(true)
.or(false)
.toString(),
),
],
),
),
泛型扩展的链式调用:这个用法非常值得一提,在原生开发中kotlin的语法糖是相当牛掰的,kotlin能够使代码的编写链成一整个链而不使用一个中间变量,这样使得代码优雅,封装的更完美。幸运的是dart虽然没有提供很多的语法糖,但却提供了泛型扩展函数,我们可以依此自定义非常强大的语法糖,调用示例如下,经过层层无聊的转化得到一个字符串而没有定义一个函数,也没有中间变量造成变量污染:
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
People(11, 1, 30)
.apply((val) {
val.introduce = "我今年${val.age}${val.sex}${val.weight}";
}).let((val) {
if (val.sex == 1) return Monkey(11, 0, 30);
return Monkey(11, 1, 30);
}).let((val) {
if (val.sex == 1) return "大猴子";
return "程序猿";
}).let((val) {
return "整这么多干啥呢,好麻烦啊";
})),
],
),
),
通过以上示例可以看出扩展函数是很有可玩性的,她能大大提高代码质量,让编程变得有趣,何不一起来探讨探讨呢?