如何使用
dart extension 的使用场景是无法修改原类的时候,通过扩展的方式来增加原类的方法,也可以增加 getter,setters,and operators。
比如
1 |
int.parse('42') |
如果 String 有 pareseInt 方法,我们可以这样写
1 |
'42'.parseInt() |
为了达到这个目标,需要写一个 Extension
1 2 3 4 5 6 |
extension NumberParsing on String { int parseInt() { return int.parse(this); } // ··· } |
然后就可以使用了。
1 2 3 4 5 |
// Import a library that contains an extension on String. import 'string_apis.dart'; // ··· print('42'.padLeft(5)); // Use a String method. print('42'.parseInt()); // Use an extension method. |
处理冲突
注意到前面加的 NumberParsing 了吗?这个是为 extension 起的名字。起名字的作用是有冲突的时候可以方便的控制显隐。比如 NumberParsing2 也定义了 parseInt 方法与 NumberParsing 的 parseInt 冲突,如果只想要 NumberParsing 的 parseInt,只需要把 NumberParsing2 隐藏就好了。
1 2 3 4 5 6 7 8 9 10 |
// Defines the String extension method parseInt(). import 'string_apis.dart'; // Also defines parseInt(), but hiding NumberParsing2 // hides that extension method. import 'string_apis_2.dart' hide NumberParsing2; // ··· // Uses the parseInt() defined in 'string_apis.dart'. print('42'.parseInt()); |
或者可以 给 NumberParsing2 经起个别名
1 2 3 4 5 6 7 8 9 10 |
import 'string_apis.dart'; import 'string_apis_2.dart' as rad; print(NumberParsing('42').parseInt()); // Use the ParseNumbers extension from string_apis_3.dart. print(rad.NumberParsing('42').parseInt()); // Only string_apis_3.dart has parseNum(). print('42'.parseNum()); |
泛型 extension
可以只给 int 类型的 list 加 sum 方法,其它类型的 list 不能使用 sum。
1 2 3 4 5 |
// Import a library that contains an extension on String. import 'string_apis.dart'; // ··· print('42'.padLeft(5)); // Use a String method. print('42'.parseInt()); // Use an extension method. |
1 2 3 |
["1", "2", "3"].sum(); //Error: The method 'sum' isn't defined for the class 'List<String>' [1,2,3].sum(); // ok, output 6 |
要注意的问题
dart extension 不可以用于 dynamic 类型
1 2 |
dynamic d = '2'; print(d.parseInt()); // Runtime exception: NoSuchMethodError |
dart extension 权限很大,这也意味着,很可能被过度使用。所以在使用的时候一定要再三权衡,一定要可读性,可维护性优先。
上面的代码是比较简单的,但是如果类型比较复杂,不明确指定类型,类似如下的形式,也是可能会报错的:
1 2 3 4 5 6 7 8 9 10 |
class Provider { late final d; Provider() { this.d = ''; this.d.parseInt(); // Runtime exception: NoSuchMethodError } } |