我想通过引用方式传递基本类型(int,bool等)。 我在这里找到了一篇相关讨论文章(段落“按引用传递值类型”):Dart中的值类型,但我仍然想知道是否有一种方法可以在Dart中实现它(除了使用对象包装器)? 有任何开发进展吗?
我想通过引用方式传递基本类型(int,bool等)。 我在这里找到了一篇相关讨论文章(段落“按引用传递值类型”):Dart中的值类型,但我仍然想知道是否有一种方法可以在Dart中实现它(除了使用对象包装器)? 有任何开发进展吗?
Dart语言目前不支持此功能,未来也许会有,但只能等待时间证明。
原始类型将按值传递,正如在此已经提到的那样,“通过引用传递原始类型”的唯一方法是将其封装起来:
class PrimitiveWrapper {
var value;
PrimitiveWrapper(this.value);
}
void alter(PrimitiveWrapper data) {
data.value++;
}
main() {
var data = new PrimitiveWrapper(5);
print(data.value); // 5
alter(data);
print(data.value); // 6
}
如果您不想那样做,那么您需要找到解决问题的另一种方法。
有些情况下,我看到人们需要通过引用传递变量是因为他们想要将某个值传递给类中的函数:
class Foo {
void doFoo() {
var i = 0;
...
doBar(i); // We want to alter i in doBar().
...
i++;
}
void doBar(i) {
i++;
}
}
在这种情况下,你可以将 i
改为一个类成员。param1 = 10
,并且希望在从方法返回时仍保持此值为10
。但是引用不是指针。当您使用=运算符为参数分配新值时,这种更改不会反映在调用方法中。这对非原始类型(类)仍然成立。class Test {
int val;
Test(this.val);
}
void main() {
Test t = new Test(1);
fn1(t);
print(t.val); // 2
fn2(t);
print(t.val); // still 2, because "t" has been assigned a new instance in fn2()
}
void fn1(Test t) {
print(t.val); // 1
t.val = 2;
}
void fn2(Test t) {
t = new Test(10);
print(t.val); // 10
}
编辑 根据评论,我尝试使我的回答更加清晰,但不知何故,我似乎无法在不引起更多混乱的情况下表达得恰当。基本上,当一个从Java转来的人说“参数按引用传递”时,他们的意思就是C/C++开发者所说的“参数作为指针传递”。
使用 List 中的值来通过引用传递变量是一种方式。因为数组或列表默认情况下是按引用传递的。
void main() {
List<String> name=['ali' ,'fana'];
updatename(name);
print(name);
}
updatename(List<String> name){
name[0]='gufran';
}
试试这个,这是传递引用最简单的方式之一。
main() {
var a = {"b": false};
print("Before passing: " + a["b"].toString());
trial(a);
print("After passing: " + a["b"].toString());
}
trial(param) {
param["b"] = true;
}
输出
Before passing: false
After passing: true
只是为了明确:
void main() {
var list1 = [0,1,2];
var modifiedList1 = addMutable(list1, 3);
var list2 = [0,1,2];
var modifiedList2 = addImmutable(list2, 3);
print(list1);
print(modifiedList1);
print(list2);
print(modifiedList2);
}
List<int> addMutable(List<int> list, int element){
return list..add(element);
}
List<int> addImmutable(List<int> list, int element){
return [...list, element];
}
输出:
[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 2]
[0, 1, 2, 3]
所有变量都是按值传递的。如果一个变量包含一个原始类型(int、bool等),那就是它的值。你可以随意使用它,不会影响源值。如果一个变量包含一个对象,它实际上包含的是对该对象的引用。
引用本身也是按值传递的,但它所引用的对象根本没有被传递。它只停留在原地。这意味着你实际上可以更改这个对象。
因此,如果你传递一个List并且使用.add()添加了一些内容,你已经在内部更改了它,就像它是按引用传递的一样。但是,如果你使用展开运算符[...list],你将创建一个全新的副本。在大多数情况下,这才是你真正想要做的。
听起来很复杂。其实不是。Dart很酷。
class Owner {
int _value = 0;
int getValue() => _value;
void increase() => _value++;
}
void main() {
final owner = Owner();
int Function() obtainer = owner.getValue;
print(obtainer());
owner.increase();
print(obtainer());
}
输出将会是:
0
1
这种方法有与内存使用相关的缺点:获取器将保留对所有者的引用,即使所有者已经没有被引用,但获取器仍然可访问, 所有者也将是可访问的,因此不会被垃圾回收。
如果您不想要这个缺点,请传递比整个所有者更小的容器:
import 'package:flutter/foundation.dart';
class ListenableAsObtainer<T> implements ValueObtainer<T> {
ListenableAsObtainer(this._listenable);
final ValueListenable<T> _listenable;
@override
T get value => _listenable.value;
}
class FunctionAsObtainer<T> implements ValueObtainer<T> {
FunctionAsObtainer(this._function);
final T Function() _function;
@override
T get value => _function();
}
class ValueAsObtainer<T> implements ValueObtainer<T> {
ValueAsObtainer(this.value);
@override
T value;
}
/// Use this interface when the client needs
/// access to the current value, but does not need the value to be listenable,
/// i.e. [ValueListenable] would be too strong requirement.
abstract class ValueObtainer<T> {
T get value;
}
FunctionAsObtainer
的使用仍会导致持有者无法进行垃圾回收,但另外两个选项则不会。
你可以使用ValueNotifier
并且,你可以将它作为ValueListenable传递给需要了解最新值但不应编辑它的类或方法:
class Owner {
final theValue = ValueNotifier(true);
final user = User(theValue);
...
}
class User {
final ValueListeneble<bool> theValue;
User(this.theValue);
...
}
它提供了比实际需要更多的功能,但解决了问题。