Why Dart Has Multiple Parameter Styles
Dart gives functions three ways to accept arguments: required positional parameters that must be supplied in order, optional positional parameters wrapped in square brackets, and named parameters wrapped in curly braces that are passed as name: value pairs. This flexibility exists because a single required-positional style forces callers to remember argument order and supply every value even when sensible defaults exist, which becomes unmanageable for functions like a Flutter widget constructor that might accept a dozen configuration options. Named and optional parameters let API designers make most arguments optional while keeping call sites self-documenting.
Cricket analogy: A team's playing XI submission form has mandatory fields — captain's name, team list — plus optional fields like 'impact substitute nomination' that you only fill in if relevant, mirroring how Dart separates required positional parameters from optional named ones.
Positional Optional Parameters
Optional positional parameters are declared inside square brackets after any required parameters, like String greet(String name, [String? title]), and if the caller omits them, they default to null unless you supply an explicit default with an equals sign, such as [String title = 'Friend']. Because they're positional, callers must supply them in the declared order and cannot skip an earlier optional parameter to reach a later one — if you want to set the third optional parameter, you must also provide the first two. This makes positional optional parameters best for a small number of arguments where order is natural and unambiguous, such as substring(startIndex, [endIndex]).
Cricket analogy: Announcing a bowling change follows a strict order — bowler's name, then optionally the specific field change, then optionally the over count reminder — and you can't skip straight to the over count without mentioning the field change first, just like Dart's ordered optional positional parameters.
String greet(String name, [String title = 'Friend']) {
return 'Hello, $title $name!';
}
void main() {
print(greet('Asha')); // Hello, Friend Asha!
print(greet('Asha', 'Dr.')); // Hello, Dr. Asha!
}Named Parameters and the required Keyword
Named parameters are declared inside curly braces, like void createUser({required String name, int age = 18, String? email}), and callers pass them by name in any order: createUser(name: 'Asha', email: 'a@x.com'). Since Dart 2.12's null safety, any named parameter without a default value must be marked required or given a nullable type, and the analyzer enforces that required named parameters are supplied at every call site, catching missing arguments at compile time rather than surfacing a null-related bug at runtime. This combination of required and named makes constructor calls in Flutter, like Text('Hello', style: TextStyle(fontSize: 18)), both flexible and self-documenting.
Cricket analogy: A DRS review request specifies details by name regardless of order — umpire's call: yes, impact: outside line, hit height: above stumps — just as Dart's named parameters let a caller supply createUser(email: ..., name: ...) in any order they choose.
class Rectangle {
final double width;
final double height;
Rectangle({required this.width, required this.height});
double get area => width * height;
}
void main() {
final rect = Rectangle(width: 10, height: 5);
print(rect.area); // 50.0
}Named parameters dramatically improve readability at the call site: compare Rectangle(10, 20, 5, 5), where the meaning of each number is invisible, to Rectangle(x: 10, y: 20, width: 5, height: 5), where every argument is self-explanatory without needing to check the function signature.
Default Values and Combining Parameter Types
A parameter, whether positional-optional or named, can specify a default value with = expression directly in the signature, and that default must be a compile-time constant — you cannot default to a value computed by calling another function at runtime. Dart does not allow mixing optional positional parameters with named parameters in the same function signature; a function may have required positional parameters plus either optional positional parameters or named parameters, but not both categories simultaneously, a rule the analyzer enforces immediately if you try to combine them.
Cricket analogy: A ground's standard pitch report defaults to 'true and even' unless the curator explicitly overrides it before a match, just as a Dart parameter's default value applies automatically unless the caller supplies an explicit override at the call site.
A common migration bug when refactoring a function from positional to named parameters is forgetting to update every call site, since named-parameter calls use name: value syntax while positional calls just pass bare values — the analyzer will flag mismatched calls, but only after you've changed the signature, so search for all call sites first.
- Dart supports required positional, optional positional ([]), and named ({}) parameters.
- Optional positional parameters must be supplied in declared order; you can't skip an earlier one.
- Named parameters are passed as name: value pairs and can appear in any order at the call site.
- Since null safety, a named parameter without a default must be marked required or given a nullable type.
- Default values must be compile-time constants, not values computed at runtime.
- A function can't mix optional positional and named parameters in the same signature.
- Named parameters make call sites self-documenting, especially for functions with many arguments.
Practice what you learned
1. How are optional positional parameters declared in a Dart function signature?
2. What must you do to make a named parameter mandatory in null-safe Dart?
3. Can a Dart function combine optional positional parameters and named parameters in the same signature?
4. What must a parameter's default value be in Dart?
5. If you call createUser(name: 'Priya', age: 25) and createUser(age: 25, name: 'Priya'), what happens?
Was this page helpful?
You May Also Like
Functions in Dart
Understand how Dart declares functions, its three parameter styles, first-class function values, recursion, and lexical scoping.
Arrow Functions and Closures
Explore Dart's compact arrow (=>) function syntax and how closures capture enclosing variables to power callbacks and higher-order functions.
Conditionals in Dart
Learn how Dart evaluates branching logic using if/else, switch statements with Dart 3 pattern matching, and compact conditional expressions like the ternary and null-aware operators.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics