有没有办法像我们在 Go(或其他一些语言)中那样在函数返回语句中返回多个值(除了返回对象)?
例如,在 Go 中我们可以这样做:
func vals() (int, int) {
return 3, 7
}
这可以在 Dart 中完成吗?像这样的东西:
int, String foo() {
return 42, "foobar";
}
更新了 Dart 3.0
在 Dart 3.0 中可以使用记录
(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
类,如包 https://pub.dev/packages/tuple 提供的。
either
了解返回值或错误的方法。
我想补充一点,Go 中多个返回值的主要用例之一是错误处理,Dart 以自己的方式处理异常和失败的承诺。
当然,这还剩下一些其他用例,所以让我们看看使用显式元组时代码的样子:
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 来说并没有太大的改进,但它确实有效、清晰,并且对于构建 UI 来说相当高效。我真的很喜欢如何快速地将东西组合在一起(有时在工作休息时从 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 添加了 records,它可用于以类型安全的方式返回多个值。
对于 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
当然可能有点不方便,但在某些情况下,这可能是值得的。
您可以使用 dartz 包返回多种数据类型
您可以使用
Set<Object>
返回多个值,
Set<object> foo() {
return {'my string',0}
}
print(foo().first) //prints 'my string'
print(foo().last) //prints 0
此功能现已在 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);
我无法使用这个解决方案。 为什么dart不支持? 谁能解释一下 Return 关键字? 我的意思是我想创建一个函数或一段代码可以执行 Return 关键字的“替代”功能。 我不是专家,谢谢。 我知道“void”返回类型可以帮助我避免使用 Return 关键字。
在 Dart 中的这种情况下,一个简单的解决方案可以返回一个列表,然后根据您的要求访问返回的列表。您可以通过索引访问特定值,也可以通过简单的 for 循环访问整个列表。
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]);
}
}