Flutter 必填关键字

Flutter required keyword

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

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

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

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

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

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

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

更新

从 Dart 2.12 开始,required 关键字取代了 @required meta annotation. For detailed info look into the official FAQ。以下答案已更新以反映此安全性和空安全性。

默认需要的参数

默认需要 class 构造函数或函数的参数。

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');

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

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

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

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');

移除

required

在构造函数中。 而是写

final String? x;

所以,它变成了:

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

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