如何获得扩展方法来更改 Dart 中的原始对象?

时间:2021-03-09 11:55:11

标签: flutter class object dart extension-methods

我有bounds。应使用新的 LatLng 扩展边界。

var bounds = LatLngBounds();
for (var latlng in _list) bounds.extend(latlng);

我想实现这个扩展:

extension LatLngBoundsExtend on LatLngBounds {
  extend(LatLng _latLng){
    //I want to change the object which this method is called from
    this = LatLngBounds(southwest: /* some magic code*/, northeast: /* some magic code*/   );

  }
}

4 个答案:

答案 0 :(得分:2)

如果原始对象的属性不是最终对象,则可以更改它。 This is not the case for LatLngBounds.southwest and LatLngBounds.northeast

答案 1 :(得分:1)

如果我没记错的话,for i in `echo https://github.com/user/{repox,repoy,repoz,repob}`; do git clone $i; done 是一个代表纬度/经度对齐的矩形的不可变类。

LatLngBounds

如果此 final myLatLngBounds = LatLngBounds(southwest, northeast); myLatLngBounds.extend(latlng); 修改了 extend,您将如何访问它? ?

我认为这个 this 应该是某种状态管理的一部分。

使用 Riverpod Hooks package 查看以下内容:

不是更改对象(因为它是不可变的),而是在扩展中返回一个新对象:

extend

然后,当您需要修改对象时,您可以处理由 Flutter 或任何其他 State Management System 管理的状态对象:

extension RectX on Rect {
  Rect extend(Offset offset) {
    return Rect.fromLTRB(
      min(left, offset.dx),
      min(top, offset.dy),
      max(right, offset.dx),
      max(bottom, offset.dy),
    );
  }
}

这是一个最小的工作示例:

enter image description here

final rectProvider =
    StateNotifierProvider<RectNotifier>((ref) => RectNotifier());

class RectNotifier extends StateNotifier<Rect> {
  RectNotifier([Rect state])
      : super(state ?? Rect.fromLTRB(100, 100, 200, 200));

  void extend(Offset offset) {
    state = state.extend(offset);
  }
}

答案 2 :(得分:1)

如果字段不是最终字段,您可以更改它们。但是您不能将对象更改为 this = new Class()

附注。 southwestnortheastfinalLatLngBounds 字段。所以你不能用扩展来改变它们 https://github.com/flutter/plugins/blob/master/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart

答案 3 :(得分:0)

扩展方法可以变异 this,但它们不能重新分配/重新绑定它。请注意,这也适用于普通方法,并非特定于扩展方法。

假设重新分配 this 是可能的。考虑以下代码:

var foo = Foo();
var sameFoo = foo;

foo.reassignThis();

foosameFoo 仍然指向同一个对象吗?如果他们现在指的是不同的对象,那将是令人惊讶的。但是,如果它们仍然引用同一个对象,那就意味着 VM/运行时需要能够轻松快速地找到对对象的所有引用,以便它可以更新它们。< /p>

即使虚拟机/运行时可以做到这一点,请考虑:

class Base {
  Base(this.x);

  int x;

  void reassignThis() {
    this = Base(x + 1); // Not legal!
  }
}

class Derived extends Base {
  Derived(int x) : super(x);

  int y;
}

void main() {
  var derived = Derived(0);
  derived.reassignThis();
  print(derived.y);
}

调用 reassignThis() 后,derived 会是什么?它仍然是一个 Derived 对象吗?它只是一个 Base 对象吗?

重新分配 this 是不可能的,也不是可以改进的东西;基本上没有多大意义。


现在,您可以实现以下内容,而不是重新分配 this

class MyLatLngBounds implements LatLngBounds {
  MyLatLngBounds(this._actual);

  LatLngBounds _actual;

  LatLng get northeast => _actual.northeast;
  LatLng get southwest => _actual.southwest;
  // ... other methods that forward to [_actual] ...

  void extend(LatLng _latLng) {
    _actual = LatLngBounds(/* some magic code */);
  }
}

然后尝试在任何地方使用 MyLatLngBounds 而不是 LatLngBounds