You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 11:54:05