繁体   English   中英

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

[英]How can I get an extension method to change the original object in Dart?

我有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*/   );

  }
}

如果原始 object 的属性不是最终的,则可以更改它。 LatLngBounds.southwestLatLngBounds.northeast并非如此

如果我没记错的话, LatLngBounds是一个不可变的 class 代表一个纬度/经度对齐的矩形。

final myLatLngBounds = LatLngBounds(southwest, northeast);
myLatLngBounds.extend(latlng);

如果这个extend修改了this ,你将如何访问它?

我认为这个extend应该是某种 State 管理的一部分。

请参阅以下内容,使用Riverpod Hooks package

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

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),
    );
  }
}

Then, when you need to modify the object, you work on a State Object managed by Flutter or any other State Management System :

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);
  }
}

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

在此处输入图像描述

import 'dart:math' show min, max;

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() {
  runApp(
    ProviderScope(
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
        home: HomePage(),
      ),
    ),
  );
}

class HomePage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final rect = useProvider(rectProvider.state);
    return Scaffold(
      body: GestureDetector(
        onTapDown: (details) =>
            context.read(rectProvider).extend(details.localPosition),
        child: Container(
          color: Colors.black12,
          padding: EdgeInsets.all(16.0),
          child: Stack(
            children: [
              Positioned(
                top: rect.top,
                left: rect.left,
                child: Container(
                    width: rect.width,
                    height: rect.height,
                    color: Colors.amber.shade400),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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);
  }
}

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),
    );
  }
}

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

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

扩展方法可以改变this ,但不能重新分配/重新绑定它。 请注意,普通方法也是如此,并不特定于扩展方法。

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

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

foo.reassignThis();

foosameFoo仍然指代相同的 object? 如果他们现在提到不同的对象,那将是令人惊讶的。 但是,如果它们仍然引用相同的 object,则意味着 VM/运行时需要能够轻松快速地找到对 object 的所有引用,以便更新它们。

即使 VM/运行时可以做到这一点,也要考虑:

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的 object 吗? 它只是一个Base object 吗?

重新分配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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM