dart扩展函数的几种用法

简介:
从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 on T {
  T apply(f(T e)) {
    f(this);
    return this;
  }

  R let(R f(T e)) {
    return f(this);
  }
}

调用示例如下:仅简单举几个调用例子,其余的调用有兴趣者自行尝试。

实现单层没有嵌的padding和点击事件

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'You have pushed the button this many times:',
            )
                    .padding(EdgeInsets.all(10))
                    .gesture(onTap: () {
              
            }),
          ],
        ),
      ),

实现String正则的判断

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '13646176072'.isMobile()?"手机号":"不是手机号",
            ),
          ],
        ),
      ),

bool类型的链式调用

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              ['13646176072', "fgdgdfgdf", 'trtreter']
                  .isNullOrEmpty()
                  .not()
                  .and(true)
                  .or(false)
                  .toString(),
            ),
          ],
        ),
      ),

泛型扩展的链式调用:这个用法非常值得一提,在原生开发中kotlin的语法糖是相当牛掰的,kotlin能够使代码的编写链成一整个链而不使用一个中间变量,这样使得代码优雅,封装的更完美。幸运的是dart虽然没有提供很多的语法糖,但却提供了泛型扩展函数,我们可以依此自定义非常强大的语法糖,调用示例如下,经过层层无聊的转化得到一个字符串而没有定义一个函数,也没有中间变量造成变量污染:

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            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 "整这么多干啥呢,好麻烦啊";
            })),
          ],
        ),
      ),

通过以上示例可以看出扩展函数是很有可玩性的,她能大大提高代码质量,让编程变得有趣,何不一起来探讨探讨呢?

你可能感兴趣的:(dart扩展函数的几种用法)