Flutter required keyword
Asked Answered
D

6

29

I don't really understand how required works. For example I've seen this code:

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

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

But what should required do here? Seems like it makes an optional parameter a non optional parameter.

Dedication answered 14/1, 2019 at 12:46 Comment(0)
R
39

Dart 2.12 (null safety):

Beginning with Dart 2.12, the @required annotation is now replaced by the required keyword. You should mark your field required if it is mandatory for others to pass some value to it.

For example:

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, 
  });
}

Usage:

Foo(); // Error: 'a' is required
Foo(a: 0); // Good
Foo(a: 0, b: 1); // Good
Renwick answered 14/1, 2019 at 13:3 Comment(9)
even if I dont mention the annotation then also it is mandatory to pass the parameter since default constructor is overloaded by this constructor. What is the use of it then?Castaway
@Castaway I didn't get you clearly, you don't need to pass any value to a if you don't annotate it with @required.Renwick
no, it is required to pass the value to a even if it is not annotated with @requiredCastaway
@Castaway I'd love if you can post a question with this detail, I can assist you better.Renwick
@Castaway Is there any problem in creating a new question?Renwick
check this code repl.it/repls/ClutteredAppropriateDriverwrapperCastaway
You're using positional arguments, not named.Renwick
Let us continue this discussion in chat.Castaway
Any idea on how to test for @required parameters in widget testing?Bate
C
58

Short answer

Using the required keyword when defining a class constructor like so:

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

means that you are required to include that parameter name and value when you create an object:

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

In this case, including parameter x was required.

Detailed explanation

Below are more details about other ways constructors and their parameters could be defined.

Parameters required by default

The parameters of a class constructor or function are required by default.

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

You're not allowed to do this:

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

You must do this:

final value = Test('hello');

Optional named parameters

If you surround a parameter with curly braces, though, in addition to becoming a named parameter, it also becomes optional.

Since it's optional, the property must either be nullable like this:

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

Or it has to have a default value like this:

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

So now this is ok:

final value = Test(); 

And so is this:

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

Required named parameters

Sometimes you don't want to allow a parameter to be null and there is no natural default variable. In that case you can add the required keyword in front of the parameter name:

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

This is not ok anymore:

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

But this is still fine:

final value = Test(x: 'hello');
Congreve answered 23/7, 2020 at 6:21 Comment(2)
It seems like this is missing why the syntax in the example (and frequently used in Dart/Flutter documentation) is used. It's requiring you to pass a public property's value, and using a shorthand to tie the constructor parameter to the property without typing a bunch of bland repeated logic out.Bibliofilm
@ChrisMoschini, you can see if the update is any better.Congreve
R
39

Dart 2.12 (null safety):

Beginning with Dart 2.12, the @required annotation is now replaced by the required keyword. You should mark your field required if it is mandatory for others to pass some value to it.

For example:

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, 
  });
}

Usage:

Foo(); // Error: 'a' is required
Foo(a: 0); // Good
Foo(a: 0, b: 1); // Good
Renwick answered 14/1, 2019 at 13:3 Comment(9)
even if I dont mention the annotation then also it is mandatory to pass the parameter since default constructor is overloaded by this constructor. What is the use of it then?Castaway
@Castaway I didn't get you clearly, you don't need to pass any value to a if you don't annotate it with @required.Renwick
no, it is required to pass the value to a even if it is not annotated with @requiredCastaway
@Castaway I'd love if you can post a question with this detail, I can assist you better.Renwick
@Castaway Is there any problem in creating a new question?Renwick
check this code repl.it/repls/ClutteredAppropriateDriverwrapperCastaway
You're using positional arguments, not named.Renwick
Let us continue this discussion in chat.Castaway
Any idea on how to test for @required parameters in widget testing?Bate
V
4

@required is an annotation that will create a warning for you to remember that the named parameter is necessary for the class to work as expected. It will not create compile errors, at least for what I know.

Volga answered 14/1, 2019 at 12:59 Comment(2)
But if that parameter is necessary, why is it set as an optional?Dedication
Mostly for code readability. Non-named parameters cannot be quickly understood by someone who is reading an object instantiation.Volga
S
2

Short answer: Named parameters are optional by default in Dart. We prefer them to positional params for ease of use. In this case, the named parameters also might be expected to hold some value all the time (non-nullable) - from initialization itself. The required keyword is needed to enforce passing values while having the readability of a named parameter. Hence, the double effort.

He could use default values for such parameters, but that may not be wanted here.

Positional parameters can be required or optional, which we pass in order when calling. The following is an example of required positional parameters' usage:

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.

Named parameters are another type of optional parameters. Flutter APIs use named parameters and in our UI code, it is preferred to use named parameters instead of positional parameters. Reason being readability and clarity when reading code or calling the constructors later on at several parts of the code. You would have seen this as the case with all Widgets, Styles. For if it were to be positional it would be difficult to keep track of them upon calling with the sheer amount of methods that would be in use, and dynamic type inference could also be at work.

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

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

NOTE: If exists, required positional parameters have to come first. Either named or optional positional params can follow(NOT BOTH).

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');
Schmuck answered 6/7, 2021 at 17:39 Comment(0)
C
1

@required bounds you to pass @required marked arguments while creating object of Class. For example, while showing a dialog, you'd mark context as required since, you cannot show dialog without having a valid context. But, you should not overuse it.

Contempt answered 14/1, 2019 at 13:5 Comment(0)
F
0

Remove

required

in constructor. Instead write

final String? x;

So, it becomes as:

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

  factory Test.initial(){
    return Test(x: "");
  }
}
Fading answered 31/3, 2022 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.