229

Dart 支持命名可选参数和位置可选参数。两者有什么区别?

另外,如何判断是否实际指定了可选参数?

4

7 回答 7

427

Dart 有两种类型的可选参数:namedpositional。在讨论差异之前,让我先讨论相似之处。

Dart 的可选参数是可选的,因为调用者在调用函数时不需要指定参数的值。

可选参数只能在任何必需参数之后声明。

可选参数可以有一个默认值,当调用者没有指定一个值时使用它。

位置可选参数

包裹的参数[ ]是位置可选参数。这是一个例子:

getHttpUrl(String server, String path, [int port=80]) {
  // ...
}

在上面的代码中,port是可选的,默认值为80.

您可以getHttpUrl使用或不使用第三个参数进行调用。

getHttpUrl('example.com', '/index.html', 8080); // port == 8080
getHttpUrl('example.com', '/index.html');       // port == 80

您可以为函数指定多个位置参数:

getHttpUrl(String server, String path, [int port=80, int numRetries=3]) {
  // ...
}

可选参数是位置port参数,如果要指定,则不能省略numRetries

getHttpUrl('example.com', '/index.html');
getHttpUrl('example.com', '/index.html', 8080);
getHttpUrl('example.com', '/index.html', 8080, 5);

当然,除非您知道 8080 和 5 是什么,否则很难说出这些看似神奇的数字是什么。您可以使用命名的可选参数来创建更具可读性的 API。

命名可选参数

包裹的参数{ }是命名的可选参数。这是一个例子:

getHttpUrl(String server, String path, {int port = 80}) {
  // ...
}

您可以getHttpUrl使用或不使用第三个参数进行调用。调用函数时必须使用参数名称。

getHttpUrl('example.com', '/index.html', port: 8080); // port == 8080
getHttpUrl('example.com', '/index.html');             // port == 80

您可以为函数指定多个命名参数:

getHttpUrl(String server, String path, {int port = 80, int numRetries = 3}) {
  // ...
}

因为命名参数是按名称引用的,所以它们可以按照与声明不同的顺序使用。

getHttpUrl('example.com', '/index.html');
getHttpUrl('example.com', '/index.html', port: 8080);
getHttpUrl('example.com', '/index.html', port: 8080, numRetries: 5);
getHttpUrl('example.com', '/index.html', numRetries: 5, port: 8080);
getHttpUrl('example.com', '/index.html', numRetries: 5);

我相信命名参数使调用站点更容易理解,尤其是当有布尔标志或上下文外的数字时。

检查是否提供了可选参数

不幸的是,您无法区分“未提供可选参数”和“提供了默认值的可选参数”这两种情况。

注意:您可以使用位置可选参数命名可选参数,但不能在同一个函数或方法中同时使用。以下是不允许的。

thisFunctionWontWork(String foo, [String positonal], {String named}) {
  // will not work!
}
于 2012-11-07T06:24:06.690 回答
50

据我了解,在 Dart 中,方法参数可以有两种类型。

  • 必需参数
  • 可选参数(位置、命名和默认)

>> 必填参数

必需参数是我们都熟悉的众所周知的旧式参数

示例

findVolume(int length, int breath, int height) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,30);

输出:

length = 10, breath = 20, height = 30

>> 可选位置参数

参数将用方括号[ ]公开,方括号中的参数是可选的。

例子:

findVolume(int length, int breath, [int height]) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,30);//valid
findVolume(10,20);//also valid

输出:

length = 10, breath = 20, height = 30
length = 10, breath = 20, height = null // no value passed so height is null

>> 可选命名参数

  • 参数将用大括号 { } 公开
  • 花括号中的参数是可选的。
  • 必须使用参数名称来分配一个用 colan 分隔的值
  • 在花括号中的参数顺序无关紧要
  • 这些类型参数有助于我们在为具有许多参数的函数传递值时避免混淆。

例子:

findVolume(int length, int breath, {int height}) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,height:30);//valid & we can see the parameter name is mentioned here.
findVolume(10,20);//also valid

输出:

length = 10, breath = 20, height = 30
length = 10, breath = 20, height = null

>> 可选默认参数

  • 与可选命名参数相同,此外我们可以为此参数分配默认值。
  • 这意味着没有传递任何值,将采用此默认值。

例子:

findVolume(int length, int breath, {int height=10}) {
 print('length = $length, breath = $breath, height = $height');
} 

findVolume(10,20,height:30);//valid
findVolume(10,20);//valid 

输出:

length = 10, breath = 20, height = 30
length = 10, breath = 20, height = 10 // default value 10 is taken

感谢此视频链接给出的清晰解释,感谢视频创作者。

视频链接:OptionalPositionalParameters

视频链接:OptionalNamedParameters

视频链接:可选默认参数

于 2019-04-26T11:41:09.877 回答
7

位置参数:

它们与默认参数相同。例如:

void add(int x, [int y = 3]);

这里 y 的默认值为 3

命名参数:

这些参数可以按任何顺序传递,方法是传递参数名称,后跟传递的值。例如:

void sum({int num1, int num2});

这个函数是这样调用的:

sum(num1: 12, num2: 24);

命名参数也可以有默认值。

于 2020-06-19T11:50:10.090 回答
7

Dart 有两种函数参数:positionalnamed.

可选位置参数

位置参数是您可能熟悉的类型:

int sumUp(int a, int b, int c) {
  return a + b + c;
}
// ···
  int total = sumUp(1, 2, 3);

使用 Dart,您可以通过将这些位置参数括在括号中来使它们成为可选参数:

int sumUpToFive(int a, [int b, int c, int d, int e]) {
  int sum = a;
  if (b != null) sum += b;
  if (c != null) sum += c;
  if (d != null) sum += d;
  if (e != null) sum += e;
  return sum;
}
// ···
  int total = sumUpToFive(1, 2);
  int otherTotal = sumUpToFive(1, 2, 3, 4, 5);

可选的位置参数总是在函数参数列表的最后。除非您提供另一个默认值,否则它们的默认值为 null:

int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) {
// ···
}
// ···
  int newTotal = sumUpToFive(1);
  print(newTotal); // <-- prints 15

Code example

实现一个函数,该函数joinWithCommas()接受一到五个整数,然后返回由逗号分隔的这些数字的字符串。以下是函数调用和返回值的一些示例:

String joinWithCommas(int a, [int b, int c, int d, int e]) {
  var total = '$a';
  if (b != null) total = '$total,$b';
  if (c != null) total = '$total,$c';
  if (d != null) total = '$total,$d';
  if (e != null) total = '$total,$e';
  return total;
}

函数调用

joinWithCommas(1)       
joinWithCommas(1, 2, 3)     
joinWithCommas(1, 1, 1, 1, 1)

返回值

'1'
'1,2,3'
'1,1,1,1,1'

可选的命名参数

使用花括号语法,您可以定义具有名称的可选参数。

void printName(String firstName, String lastName, {String suffix}) {
  print('$firstName $lastName ${suffix ?? ''}');
}
// ···
  printName('Avinash', 'Gupta');
  printName('Poshmeister', 'Moneybuckets', suffix: 'IV');

如您所料,这些参数的值默认为 null,但您可以提供默认值:

void printName(String firstName, String lastName, {String suffix = ''}) {
  print('$firstName $lastName $suffix');
}

一个函数不能同时具有可选的位置参数和可选的命名参数。

代码示例

copyWith()实例方法添加到 MyDataObject 类。它应该采用三个命名参数:

int newInt
String newString
double newDouble

调用时,应基于当前实例copyWith()返回一个新实例,并将来自前面参数(如果有)的数据复制到对象的属性中。MyDataObject例如,如果newInt为非空,则将其值复制到anInt.

class MyDataObject {
  final int anInt;
  final String aString;
  final double aDouble;

  MyDataObject({
     this.anInt = 1,
     this.aString = 'Old!',
     this.aDouble = 2.0,
  });

  // Add your copyWith method here:
}
于 2021-01-22T03:13:40.033 回答
5

当使用“paramName : value”语法指定函数的参数时,它就是命名参数。通过将这些参数括在 [ 和 ] 括号之间,可以将它们呈现为可选的。可以在以下 Hello World 程序中演示此功能的基本演示:

sayHello([String name = ' World!']) {
  print('Hello, ${name}');
}

void main() {
  sayHello('Govind');
}
于 2018-09-29T11:14:20.953 回答
3

doc中我们得到positionalnamed参数都是可选的,这意味着它们都可以不存在。

在我看来,named参数比参数更严格positional。例如,如果您声明这样一个方法:

String say({String from, String msg})

上面frommsgnamed参数,调用方法say时必须使用say(from: "xx", msg: "xx"). 钥匙不能缺席。

然而,如果你使用位置参数,你是自由的。

于 2019-01-07T13:15:18.860 回答
2

来自 Flutter 的示例

命名参数

类构造Duration函数采用命名参数:

const Duration(
{int days = 0,
int hours = 0,
int minutes = 0,
int seconds = 0,
int milliseconds = 0,
int microseconds = 0}
)

位置参数

DateTime的构造函数有 1 个必需的位置参数和 7 个可选的位置参数:

DateTime(
int year,
[int month = 1,
int day = 1,
int hour = 0,
int minute = 0,
int second = 0,
int millisecond = 0,
int microsecond = 0]
)

什么时候用哪个?

对于dates/times,如果您不指定月份,则指定一天是没有意义的。如果我在星期一告诉你,你不会知道我说的是哪个星期一。如果您指定月份但不指定年份,则没有意义。日期自然从粗到细。当然,实际上你会假设下周一是哪个星期一,但程序不能这样假设。

对于Duration,您指定哪个都没有关系。A Duration of time 可以是 1 秒、1 毫秒或 5 天。如果我告诉你等待 5 秒,我不需要告诉你0 天 0 小时 0 分钟 5 秒

于 2021-09-19T14:31:10.120 回答