19

我真的不明白如何required工作。例如我看过这段代码:

class Test{
  final String x;
  Test({
    required this.x
  });

  factory Test.initial(){
    return Test(x: "");
  }
}

但是required这里应该怎么做?似乎它使可选参数成为非可选参数。

4

5 回答 5

42

更新

从 Dart 2.12 开始,required关键字替换了@required 注释。有关详细信息,请查看官方常见问题解答。以下答案已更新以反映此安全性和空安全性。

默认需要的参数

默认情况下,类构造函数或函数的参数是必需的。

class Test {
  final String x;
  Test(this.x);
}

你不能这样做:

final value = Test(); 
// 1 positional argument(s) expected, but 0 found.

你必须这样做:

final value = Test('hello');

可选的命名参数

但是,如果用花括号将参数括起来,除了成为命名参数之外,它还成为可选参数。

由于它是可选的,因此该属性必须可以为空,如下所示:

class Test {
  final String? x;
  Test({this.x});
}

或者它必须有一个像这样的默认值:

class Test {
  final String? x;
  Test({this.x = ''});
}

所以现在可以了:

final value = Test(); 

这是这样的:

final value = Test(x: 'hello'); 

必需的命名参数

有时您不想允许参数null存在,并且没有自然的默认变量。在这种情况下,您可以required在参数名称前添加关键字:

class Test {
  final String x;
  Test({required this.x});
}

这已经不行了:

final value = Test(); 
// The named parameter 'x' is required, but there's no corresponding argument.

但这仍然很好:

final value = Test(x: 'hello');
于 2020-07-23T06:21:32.143 回答
27

Dart 2.12(零安全):

从 Dart 2.12 开始,@required注释现在被required关键字替换。required如果其他人必须将某些值传递给它,您应该标记您的字段。

例如:

class Foo {
  final int a; // Mandatory? Use 'required'
  final int b; // Not mandatory? Don't use 'required'

  Foo({
    required this.a, // Marked 'required'
    this.b = 1, 
  });
}

用法:

Foo(); // Error: 'a' is required
Foo(a: 0); // Good
Foo(a: 0, b: 1); // Good
于 2019-01-14T13:03:02.417 回答
4

@required 是一个注释,它将创建一个警告,让您记住命名参数对于类按预期工作是必需的。它不会产生编译错误,至少据我所知。

于 2019-01-14T12:59:08.600 回答
1

@required 限制您在创建 Class 对象时传递 @required 标记的参数。例如,在显示对话框时,您可以根据需要标记上下文,因为没有有效上下文就无法显示对话框。但是,你不应该过度使用它。

于 2019-01-14T13:05:33.763 回答
0

简短的回答:命名参数在 Dart 中默认是可选的。为了便于使用,我们更喜欢它们而不是位置参数。在这种情况下,命名参数也可能会一直保持一些值(不可为空)——从初始化本身开始。因此,双重努力。

如果值是编译时常量,他可以使用参数的默认值初始化而不是“必需”,而这里似乎不是这种情况。

位置参数可以是必需的,也可以是可选的,我们在调用时按顺序传递。以下是所需位置参数的用法示例:

class Object{
  String name;
  int value;
  
  Object(this.name, this.value=100); //auto type inference
}

final one = Object("Name here", 50); // All parameters are needed to call.

命名参数是另一种类型的可选参数。Flutter API 使用命名参数,在我们的 UI 代码中,最好使用命名参数而不是位置参数。原因是阅读代码或稍后在代码的几个部分调用构造函数时的可读性和清晰度。您会看到所有小部件、样式都是如此。因为如果它是定位的,那么在调用大量将要使用的方法时很难跟踪它们,并且动态类型推断也可能在起作用。

void display({required String name, int value1, int value2=100}) {...;} //named params

display(value1: 50, name: "Calculated name");

注意: 如果存在,则必须先出现所需的位置参数。可以跟随命名或可选的位置参数(不是两者)

String say(String from, String msg, [String? device]) { //req. pos params and opt pos params.
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

assert(say('Bob', 'Howdy') == 'Bob says Howdy');
于 2021-07-06T17:39:28.010 回答