使用 dart extension

669 阅读1分钟

如何使用

dart extension 的使用场景是无法修改原类的时候,通过扩展的方式来增加原类的方法,也可以增加 getter,setters,and operators。

比如

int.parse('42')

如果 String 有 pareseInt 方法,我们可以这样写

'42'.parseInt()

为了达到这个目标,需要写一个 Extension

extension NumberParsing on String {
  int parseInt() {
    return int.parse(this);
  }
  // ···
}

然后就可以使用了。

// 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 隐藏就好了。

// 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 经起个别名

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。

extension  on List<int> {
  int sum() {
    return fold(0, (sum, v) => sum + v);
  }
}
["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 类型

dynamic d = '2';
print(d.parseInt()); // Runtime exception: NoSuchMethodError

dart extension 权限很大,这也意味着,很可能被过度使用。所以在使用的时候一定要再三权衡,一定要可读性,可维护性优先。