Dart如何为Uri类添加getter、setter扩展方法并解决相关报错
Dart 为Uri类添加自定义getter/setter扩展方法解决方案
错误原因
- Dart扩展语法不支持为原有类新增实例存储字段,你代码中的
_foo不属于Uri类也不属于扩展作用域,没有实际存储空间,访问会直接报错。 - 如果直接写
set foo(val) => foo = val,相当于setter调用自身,会触发无限递归最终栈溢出。
解决方案
方案1:附加自定义私有属性(不修改Uri原有内容)
如果需要给Uri实例附加和Uri本身结构无关的自定义属性,使用Expando存储属性值,Expando会将属性和原实例绑定,实例被回收时对应存储的属性也会自动清理:
// 顶层定义Expando实例,专门存储Uri对应的foo属性值 final _uriFooExpando = Expando<String>('Uri.foo'); extension UriFooExtension on Uri { String? get foo => _uriFooExpando[this]; set foo(String? val) => _uriFooExpando[this] = val; } void main() { var uri = Uri.parse('https://example.com'); uri.foo = 'bar'; print(uri.foo); // 输出:bar }
注意事项
- Expando的键不能为null,仅能给非空的Uri实例附加属性。
- 如果需要非空返回值,可以在getter中添加默认值处理,例如
String get foo => _uriFooExpando[this] ?? ''。
方案2:封装Uri query参数操作
如果你的foo属性是需要读写Uri的query参数,由于Uri是不可变类,所有属性都是final修饰,修改参数会生成新的Uri实例,写法如下:
extension UriQueryFooExtension on Uri { // 读取query中的foo参数 String? get foo => queryParameters['foo']; // 设置foo参数,返回修改后的新Uri实例 Uri updateFoo(String? val) { final newParams = Map<String, String>.from(queryParameters); if (val == null) { newParams.remove('foo'); } else { newParams['foo'] = val; } return replace(queryParameters: newParams); } } void main() { var uri = Uri.parse('https://example.com'); // 接收返回的新Uri实例 uri = uri.updateFoo('bar'); print(uri.foo); // 输出:bar print(uri); // 输出:https://example.com?foo=bar }
内容的提问来源于stack exchange,提问作者Max888
相关产品推荐
相关产品推荐

