extension —— 无侵入扩展 Dart 类

前言

在做 iOS 开发的时候,Objective-C 语言有个特性,叫 Category,也就是可以在不修改原有类代码的基础上扩展一个类的方法或静态属性。Dart 语言同样借鉴了这种设计,只是换了个更贴切的说法,叫做 extension。通过 extension 可以以无侵入的方式扩展一个已有的类,从而不影响其他使用这个类的代码。本篇来介绍 extension 的使用以及典型的应用。

extension 介绍

要使用Dart 的 extension 扩展类很简单,只需要新增一个 Dart 文件,然后按下面的方式声明即可:

dart 复制代码
extension [扩展名称] on [已有类名] {
  static const [静态属性] = ...;

  [已有类名] get [get属性] = ...;

  [方法名](参数) {
    //方法体
  }
}

这里需要注意,extension不支持扩展非静态属性。

应用之扩展颜色

我们在 App 中经常会依据设计规范设置主题色、辅助色、标题字体颜色、分割线颜色等等。虽然可以通过 Theme 来实现,但是 Theme依赖于 Context。我们也可以定义一个主体颜色扩展,来定义我们所需要的颜色,当设计稿更改颜色时,只需要更改这个颜色扩展就可以完成所有颜色的修改。下面是示例代码:

dart 复制代码
extension ThemeColor on Color {
  static const primaryColor = Color(0xFF0990EC);
  static const lineColor = Color(0xFFEEEEEE);

  //反色
  Color get reverseColor {
    return Color.fromARGB(
      alpha,
      255 - red,
      255 - green,
      255 - blue,
    );
  }
	// 将颜色转换为16进制字符串表示,例如:#FFFF0000
  String toHex() {
    return '#${value.toRadixString(16).padLeft(6, 'F').toUpperCase()}';
  }
}

应用之屏幕适配

设计师提供的设计稿通常会按照某一个屏幕的宽度尺寸设计,例如375是设计师常用的一个设计宽度。但是实际屏幕的宽度却五花八门,这个时候就需要做屏幕适配。在 Flutter 屏幕适配插件中,screen_util 是应用最为广泛(中文文档:github.com/OpenFlutter...)。如果我们去看里面的源码,就会发现里面就用到了extension,其中典型的就是扩展了 num 类。

dart 复制代码
extension SizeExtension on num {
  ///[ScreenUtil.setWidth]
  double get w => ScreenUtil().setWidth(this);

  ///[ScreenUtil.setHeight]
  double get h => ScreenUtil().setHeight(this);

  ///[ScreenUtil.radius]
  double get r => ScreenUtil().radius(this);

  ///[ScreenUtil.diagonal]
  double get dg => ScreenUtil().diagonal(this);

  ///[ScreenUtil.diameter]
  double get dm => ScreenUtil().diameter(this);

  ///[ScreenUtil.setSp]
  double get sp => ScreenUtil().setSp(this);

  //...
}

原理上其实就是用实际屏幕尺寸与设计稿尺寸计算比例,然后再将这个比例乘以定义组件尺寸的数值。比如20.w,实际上就是20乘以换算的比例得到适配后的宽度。典型的例子就是一个固定宽度的 Container,屏幕越大应该宽度越宽,这样两侧的留白也不至于过宽。 这里我们还可以发现,如果是在父类上进行扩展,那么这些扩展对子类也是可以生效的。比如上面扩展的是 num 类,那么对于 doubleint 这样的子类也是可以用 num 类的扩展方法的。

应用之简化校验

第三类应用就是表单校验,实际上大部分都是字符串校验,那么我们可以编写一个字符串校验扩展类,将我们用到的字符串校验集中在一起,如下所示。

dart 复制代码
extension StringValidator on String {
  bool get isEmail {
    //邮箱校验逻辑
  }

  bool get isIdNumber {
    //身份证号校验
  }

  bool get isMobile {
    //手机号校验
  }

  //...
}

这样用起来会更方便,如下所示:

dart 复制代码
if (!email.isEmail) {
  //邮箱校验失败处理
}

if (!mobile.isMobile) {
  //手机号校验失败处理
}

相比单独定义一个校验类,编写静态方法来说,这样的方式的代码显然更加简洁。

总结

代码开发的一个重要原则是"对扩展开放,对修改封闭"。这是因为扩展的代码不会影响已有的业务代码,而修改则会影响所有用到修改部分的代码。使用 extension 就很好地遵循了这一原则,不更改原有的类代码,因此不影响类的原有使用方式。同时,又扩展了类的特性,使得扩展后的代码可以适用特定的场景。如果你在开发 Flutter 的应用中,发现经常要对某个类进行相同的处理,那么或许使用 extension 扩展会是一个更好的选择。

我是岛上码农,微信公众号同名。如有问题可以加本人微信交流,微信号:island-coder

👍🏻:觉得有收获请点个赞鼓励一下!

🌟:收藏文章,方便回看哦!

💬:评论交流,互相进步!

相关推荐
恋猫de小郭1 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
一只大侠的侠6 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
未来侦察班9 小时前
一晃13年过去了,苹果的Airdrop依然很坚挺。
macos·ios·苹果vision pro
renke33649 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端