[英]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.southwest
和LatLngBounds.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。 southwest
和northeast
是LatLngBounds
的final
字段。 所以你不能用扩展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();
foo
和sameFoo
仍然指代相同的 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.