Dart 点将台 | extension 拓展方法
1. Dart 的拓展方法介绍
如果我们需要判断该字符串 是否是手机号
,需要写个 正则
来校验,如果用的地方很多,每个地方都要些校验逻辑,或者抽离一个工具类辅助校验。但也没有想过可以直接使用 字符串.isPhone()
来校验?在 Dart 2.7,添加了 拓展方法
的特性,这使我们在 不修改
已有源码的基础上,可以方便地拓展 已有类型
的方法。代码如下:
main(){
String number = "18715079389";
print(number.isPhone()); // true
String number2 = "28715079389";
print(number2.isPhone()); // false
}
extension JudgeString on String {
bool isPhone(){
return RegExp(r'^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$').hasMatch(this);
}
}
拓展方法的语法如下,关键字为 extension
、 on
,其中 名称
任意,类型就是待拓展类。 {}
内可以包含若干个方法体。

2. 拓展方法中的 this
拓展方法中可以使用 this
对象,那么这个 this
对象是什么呢?第一感觉,应该指的是调用这个方法的对象。下面通过一个小案例测试一下是不是这样的。如下,对 List
类进行拓展,有一个 check
方法,需要一个 List
入参,这样我们可以比较 入参
和 this
的内存地址是不是同一个,使用 identical
方法进行比较。结果是 true 。这就说明:
拓展方法中的 this
确实指代的是 方法的调用者
。
main() {
List<int> list = [0, 1, 2, 3];
list.check(list);
}
extension ListPrint on List {
void check(List list) {
print(identical(list, this)); // true
}
}
另外也可以进行 运算符重载
的拓展。比如 DateTime
类中只是使用 add 方法进行加法计算。可以通过 extension
对原有的 DateTime
类进行运算符拓展。代码如下:
main() {
final DateTime birthday = DateTime(1994, 3, 28, 14, 28);
// 1994-07-06 16:30:00.000
print(birthday + Duration(days: 100, hours: 2, minutes: 2));
}
extension DateTimeExt on DateTime {
DateTime operator +(Duration other) => this.add(other);
}
3.拓展方法的注意点
拓展方法只能由对象调用,其名称 不可以
实例化使用。

拓展方法中 不可以
声明普通成员变量。

那你也许会有疑问,拓展名不能用,那他存在的价值是什么?拓展方法中虽然不能定义普通成员变量,但是可以定义 静态成员
。通过 名称.静态成员
可以访问。

那能拓展 静态方法
吗? 其实我们可以反过来想一想,拓展方法需要对象调用。静态方法是在实例化之前就已确定的,所以 this 是不可能在 static 方法中使用的。

这时可能有小机灵鬼会说,不用 this 不就行了吗?那不用 this ,拓展方法的意义何在?如下,在 ListPrint
中定义的静态方法,只能通过 ListPrint
调用,不能通过 List
调用。所以静态相关的和待拓展类并没有关系,是属于自己的行为。

4.拓展方法的优缺点
拓展方法的好处在使用起来非常方便,语义性也很强,复用性也很好,还能装逼于无形。
但 是药三分毒
,如果名字没起好,或说拓展的方法非常杂乱,那在别人眼中,阅读你的代码将会非常吃力。或者会让别人疑惑: 为什么我的类里没有这个方法,难道我的版本太低了?
这样,对于拓展方法而言,就会出现一些混乱,这也是 使用者
和 观看者
的信息不对等,而出现的理解性偏差。
其实这和贫富差距一样,是很难避免的,也并没有什么好的解决方案。在写拓展方法时注意命名的合理,多写注释,多写注释,多写注释,这样可以让 信息尽可能多的对等
,毕竟你的脑子里想什么,别人很难捉摸出来。
其次就是规范性,如果拓展方法可以有一个 标识来区分
,这样就能让信息拥有 辨识性
。比如,拓展方法的末尾都加 $
字符。如果这成为了一种拓展规范,这样当读码的人看到,就可以迅速意识到这个方法是 拓展的
,从而减少不必要的疑虑。

另外, 写码者
,可以通过 $
来触发提示,获取自己拓展的方法,能更快找到。

这里只是我的一个小想法,至于为什么是 $
, $
为什么在末尾,其实并不重要,重要的是规范性的普及。就像章北海的最后一句话: 没关系的,都一样
。关于 Dart 的拓展方法也说得差不多了,本文就到这里,谢谢观看 ~