除了返回一个对象之外,在函数返回语句中是否有一种方法可以返回多个值,就像我们可以在Go(或其他某些语言)中做的那样?
例如,在Go中,我们可以这样做:
func vals() (int, int) {
return 3, 7
}
这个能在Dart中实现吗?类似于这样:
int, String foo() {
return 42, "foobar";
}
除了返回一个对象之外,在函数返回语句中是否有一种方法可以返回多个值,就像我们可以在Go(或其他某些语言)中做的那样?
例如,在Go中,我们可以这样做:
func vals() (int, int) {
return 3, 7
}
这个能在Dart中实现吗?类似于这样:
int, String foo() {
return 42, "foobar";
}
更新至Dart 3.0
在Dart 3.0中可以使用记录(records)
(int, String) foo() {
return (42, "foobar");
}
void main() {
var (a,b) = foo();
print("int: ${a}");
print("String: ${b}");
}
原始答案
Dart不支持多个返回值。
您可以返回一个数组,
List foo() {
return [42, "foobar"];
}
Tuple
类。either
来实现返回值或错误的方式。tuple
的+1赞同,它与Go所做的内置功能最接近。它只是没有内置到Dart中,可能还没有太多需求,他们希望保持语言尽可能轻量级。 - Robert Jack WillList<dynamic>
或 List<Object>
。 - Günter Zöchbauer我想补充一下,Go语言中多返回值的主要用途之一是错误处理,而Dart则使用异常和失败的Promise来处理。当然还有其他一些用例,那么让我们看看在使用显式元组时代码是什么样子的:
import 'package:tuple/tuple.dart';
Tuple2<int, String> demo() {
return new Tuple2(42, "life is good");
}
void main() {
final result = demo();
if (result.item1 > 20) {
print(result.item2);
}
}
虽然不是非常简洁,但代码整洁且表现力强。我最喜欢的是,一旦你的快速实验项目真正起飞并开始添加功能并需要增加更多结构以保持控制,它基本上不需要太多改动。
class FormatResult {
bool changed;
String result;
FormatResult(this.changed, this.result);
}
FormatResult powerFormatter(String text) {
bool changed = false;
String result = text;
// secret implementation magic
// ...
return new FormatResult(changed, result);
}
void main() {
String draftCode = "print('Hello World.');";
final reformatted = powerFormatter(draftCode);
if (reformatted.changed) {
// some expensive operation involving servers in the cloud.
}
}
所以,是的,它并没有比Java有太大的改进,但它能够正常运行、清晰且相当高效地构建用户界面。我真的很喜欢如何能够快速地拼凑东西(有时在工作间歇时间在DartPad上开始),然后在我知道项目将长期存在并增长时再添加结构。
import 'dart:core';
class Tuple<T1, T2> {
final T1 item1;
final T2 item2;
Tuple({
required this.item1,
required this.item2,
});
factory Tuple.fromJson(Map<String, dynamic> json) {
return Tuple(
item1: json['item1'],
item2: json['item2'],
);
}
}
随便怎么称呼都可以!
Tuple<double, double>(item1: i1,item2: i2);
or
Tuple<double, double>.fromJson(jsonData);
您可以创建一个类来返回多个值。例如:
class NewClass {
final int number;
final String text;
NewClass(this.number, this.text);
}
生成数值的函数:
NewClass buildValues() {
return NewClass(42, 'foobar');
}
打印:
void printValues() {
print('${this.buildValues().number} ${this.buildValues().text}');
// 42 foobar
}
正如其他答案所指出的那样,Dart 3.0 添加了记录,可以用于以类型安全的方式返回多个值。
对于早期版本的Dart,返回多个值的正确方法是将这些值存储在一个类中,无论是您自己的自定义类还是Tuple
。然而,为每个函数定义一个单独的类非常不方便,使用Tuple
可能会出现错误,因为成员没有有意义的名称。
另一种(虽然有点丑陋,但不太符合Dart风格)的方法是尝试模仿C和C++通常使用的输出参数方法。例如:
class OutputParameter<T> {
T value;
OutputParameter(this.value);
}
void foo(
OutputParameter<int> intOut,
OutputParameter<String>? optionalStringOut,
) {
intOut.value = 42;
optionalStringOut?.value = 'foobar';
}
void main() {
var theInt = OutputParameter(0);
var theString = OutputParameter('');
foo(theInt, theString);
print(theInt.value); // Prints: 42
print(theString.value); // Prints: foobar
}
对于调用者到处使用variable.value
可能有点不方便,但在某些情况下这可能是值得的。
现在Dart 3.0(Flutter 3.10.0)已经可以使用了。它们被称为"记录"(完整文档在此处)。
以下是我最喜欢的一些例子:
返回类型
(int x, double y) geoLocation(String name) =>
return (-1, 36.8219);
访问它们:
var record = ('first', a: 2, b: true, 'last');
print(record.$1); // Prints 'first'
print(record.a); // Prints 2
print(record.b); // Prints true
print(record.$2); // Prints 'last'
变量
// Record type annotation in a variable declaration:
(String, int) record;
// Initialize it with a record expression:
record = ('A string', 123);
命名参数!
// Record type annotation in a variable declaration:
({int a, bool b}) record;
// Initialize it with a record expression:
record = (a: 123, b: true);
Set<Object>
来返回多个值,Set<object> foo() {
return {'my string',0}
}
print(foo().first) //prints 'my string'
print(foo().last) //prints 0
List func() {
return [false, 30, "Ashraful"];
}
void main() {
final list = func();
// to access specific list item
var item = list[2];
// to check runtime type
print(item.runtimeType);
// to access the whole list
for(int i=0; i<list.length; i++) {
print(list[i]);
}
}