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

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


Dart有两种可选参数:named和positional。在讨论不同之处之前,让我先讨论一下相似之处。

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]) {
  // ...
}

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

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!
}

当一个函数的形参使用“paramName: value”语法指定时,它就是一个命名形参。这些参数可以通过将它们括在[和]括号中来表示为可选的。这个函数的基本演示可以在下面的Hello World程序中演示:

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

void main() {
  sayHello('Govind');
}

从doc中我们得到位置形参和命名形参都是可选的,这意味着它们都可以不存在。

在我看来,命名参数比位置参数更严格。例如,如果你声明这样一个方法:

String say({String from, String msg})

上面的from和msg是命名参数,当你调用方法say时,你必须使用say(from: "xx", msg: "xx")。钥匙不能没有。

但是,如果使用位置参数,则可以自由使用。


在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

>>可选命名参数

参数将用花括号{}来表示。 花括号的参数是可选的。 必须使用参数name分配一个用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

视频链接:OptionalDefaultParameters


位置参数:

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

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

这里y的默认值是3

命名参数:

这些参数可以以任何顺序传递,只需将参数名后跟传递的值。例如:

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

这个函数是这样调用的:

sum(num1: 12, num2: 24);

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


颤振例子

命名参数

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]
)

什么时候用哪个?

对于日期/时间,如果不指定月份,那么指定一天是没有意义的。如果我告诉你星期一,你不会知道我说的是哪一个星期一。如果指定一个月而不指定一年,这是没有意义的。枣自然地由粗变细。当然,在现实中,您会假设下周一是哪一个星期一,但是程序不能这样假设。

对于Duration,指定哪个无关紧要。取值范围:1秒、1毫秒、5天。如果我告诉你等5秒,我不需要告诉你0天0小时0分5秒。


以下方法:

getBMI(float weight, float height, {int age = 80}) {
  // method body
}

体重和身高为位置参数,年龄为命名参数。

我们将像下面这样调用该方法:

getBMI(65, 175, age: 35);

正如你所看到的,maned参数使呼叫站点更容易理解。