问题 有没有办法在Dart中通过引用传递原始参数?


我想通过引用传递一个原语(int,bool,...)。我在这里找到了关于它的讨论(段落“通过引用传递值类型”): Dart中的值类型,但我仍然想知道是否有办法在Dart中做到这一点(除了使用对象包装器)?任何发展?


1078
2017-08-15 17:32


起源

我很好奇,你的用例是什么?你为什么要这样做? - Shailen Tuli
@ShailenTuli你自己等同于什么?有什么区别?我们都活过一次,所有人都不同。我们都有不同的兴趣。我们很少使用的东西。但这并不意味着他们不需要。 - mezoni
对不起,我不明白这个评论。我只是想了解提问者的意图。 - Shailen Tuli
我并不感到惊讶(好奇)有人需要它。另外,我对Dart语言中遗漏的内容并不感到惊讶。它很有用,但并不重要。 - mezoni
@mezoni理解为什么有人想做某事可以建议实现同样效果的替代方法。 - Pixel Elephant


答案:


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 一个班级成员。


6
2017-08-16 12:38



您的包装器不是通用的,但语言允许这种改进。 - mezoni
如果你是仿制药,一定要继续。我相信这是解释这一点的最简单方法。 :) - Kai Sellgren
你的回答 - Dart语言不支持这个,我怀疑它会永远。有什么问题?这可以在Dart和Dart2JS中实现此功能。许多提议的功能可以实现和结构化,以便有效地编译成Javascript。问题在于Dart团队专注于修复错误和Web客户端改进。我想这将在未来实施。我没有发现阻止这种情况的问题。我认为你的工作远非编译器设计?我是对的? - mezoni
我从来没有说过有问题。 I doubt 意味着我怀疑这个功能到了。这只是一个意见,我基于我迄今为止在达特世界所听到和看到的内容。 Dart有一定的目标群体和某些用例。该功能可能会在未来到来,而且推测是没有意义的。就像推测天气一样,可以为类型定义方差。我怀疑它永远不可能,但我不知道。 - Kai Sellgren
来自@ Eric的问题中的链接:“缺少值传递不是由于与Javascript的交互。它是对象模型的核心部分。它在Smalltalk,Ruby,Java等中都是一样的。对象通过引用传递。“ - Benji XVI


不,包装是唯一的方法。


3
2017-08-15 19:32





它们通过引用传递。这无关紧要,因为“原始”类型没有改变其内部价值的方法。

如果我错了,请纠正我,但也许你误解了“通过​​引用传递”是什么意思?我假设你想做点什么 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 ++开发人员会说“参数作为指针传递”。


3
2017-08-16 08:31



@mezoni:你的定义不是“通过引用传递”的意思吗?如果参数是按值传递的,那么我的例子中的fn1()将不会像它那样工作,不是吗? - MarioP
好吧,我的观点是Dart中没有任何真正的原始类型。 num,int,double,bool - 这些都是对象,当作为参数传递时,它们的行为与“复杂”类相同。另外,我认为我们两个意思都是一样的,只是用不同的方式命名。 “通过引用传递”是指传递对象的引用,并且在函数返回后对象成员的更改仍然存在。我们现在在同一页吗? :) - MarioP
如果有人知道如何在我的回答中更清楚地说明这一点,请随意编辑它,因为我真的不知道我该怎么说。 : - / - MarioP
@mezoni啊,现在我明白了。我正在使用Java术语,例如,“通过引用传递”与C / C ++中的含义不同。我会编辑我的答案,以反映这种差异,如果我能想到一种方法,不要让它更令人困惑。 :-S - MarioP
我认为“通过复制/值传递”意味着“发送副本,原始不能被修改”,并且“通过引用传递”意味着“发送对象/地址本身,它可以被修改”。 - Eric Lavoie