Reputation: 684
TL;DR: Named parameters are optional as a result of a conscious design choice. Short of having official language support, is there any way to enforce (and inform) required named arguments?
I find it extremely useful to use named parameters when defining a class. Take, for instance, an Ability
in an MMORPG:
class Ability {
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
effectDuration
and recast
both carry the same type of information (i.e. duration of time) and are likely represented by the same datatype. It is easy to mix up which number goes where. However, they are both information vital to the correctness of the object, so they can't be missing during instantiation.
I could just break the program via a try-catch to enforce the requirement of those parameters, but that doesn't sound like fun for someone who uses the class and has no idea (short of reading the docs and understanding intuitively what the class does) that they are required.
Is there any way to enforce the requirement of certain named parameters while managing to inform the caller of said requirement and/or help them use it correctly?
Upvotes: 35
Views: 47813
Reputation: 81
If you want declare to a empty variable but that has methods inside , you can:
1)Use the late
keyword
2)Declare the type like possible null
returned example: int? number;
3)Initialize the variable empty, for example :
List listOfNumbers = [];
Map mapOfPerson1 = {};
And so you can use the methods of the variable to add them values
Upvotes: -2
Reputation: 268134
Non-nullable named parameter:
You need to either mark the named parameter required
or provide a default value or even mark it late
. For example:
class Foo {
final int a;
final int b;
late final int c; // Mark late and provide value later.
Foo({
required this.a, // Mark required.
this.b = 0, // Provided a default value.
});
}
Nullable named parameter:
You don't need anything special to handle them.
class Foo {
final int? z;
Foo({
this.z,
});
}
Upvotes: 1
Reputation: 40493
In dart 2.0 the required
keyword has been added to the language as part of the null-safety update. This means that you get a compiler-enforced non-null value rather than one checked by the analyzer; this makes the null check completely redundant.
This means that this code does effectively the same as the old code below, except that you never have to worry about the assertion throwing as the values for name
, effectDuration
, and recast
cannot be null.
class Ability {
final String name;
final Duration effectDuration;
final bool recast;
final String? description;
Ability({
required this.name,
this.effectDuration = Duration(seconds: 1),
this.recast = false,
this.description,
});
}
Yes, there is!
Here's an example:
class Ability {
final String name;
final Duration effectDuration;
final bool recast;
final String description;
Ability({
@required this.name,
this.effectDuration = new Duration(seconds: 1),
this.recast = false,
this.description,
}):
assert(name != null),
assert(effectDuration != null);
}
You don't have to assert that name is not equal to null, but it might be useful for you.
Upvotes: 20
Reputation: 1715
As of 2.12 with null safety you can use required
keyword (not @required
). Also no need to import any additional packages.
In this example named parameter name
is optional while effectDuration
and recast
are required.
class Ability {
final name;
final effectDuration;
final recast;
Ability({this.name, required this.effectDuration, required this.recast});
}
Update pubspec.yaml
, for example:
environment:
sdk: ">=2.12.0-0 <3.0.0"
References:
Upvotes: 6
Reputation: 512306
Although you could use the flutter foundation
package as described in the accepted answer, when I am working with model classes that don't need to know about Flutter, I prefer to use the meta package directly. That way it doesn't create an unnecessary dependency on the framework. This allows you to share the Dart code even outside of Flutter.
Add meta to pubspec.yaml:
dependencies:
meta: ^1.1.7
Import it in your class file:
import 'package:meta/meta.dart';
Use the @required
annotation in your code:
class Person {
String name;
int age;
Person({@required this.name, this.age,});
}
So name
is a required parameter, but age
isn't.
final person = Person(name: 'Bob');
Update:
In an upcoming version of Dart, the required
keyword should be added by default, so no imports will be necessary at all.
Upvotes: 8
Reputation: 657761
The meta package provides a @required
annotation that is supported by the DartAnalyzer.
Flutter uses this a lot and provides @required
directly from import 'package:flutter/foundation.dart'
foo({@required String name}) {...}
foo(); // results in static warning
@required
doesn't check if the passed value is null
or not, only that a value was actually passed on the call site.
To check for null
you can also use assert()
to check for passed values
class Ability {
Ability(this.name, this.effectDuration, this.recast) : assert(name != null), assert(effectDuration != null), assert(recast != null);
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
Upvotes: 51