Flutter for Beginners
上QQ阅读APP看书,第一时间看更新

Function parameters

A function can have two types of parameters: optional and required. Additionally, as with most modern programming languages, these parameters can be named on call to make the code more readable. 

The parameter type doesn't need to be specified; in this case, the parameter assumes the dynamic type: 

  • Required parameters: This simple function definition with parameters is achieved by just defining them in the same way as most other languages. In the following function, both name and additionalMessage are required parameters, so the caller must pass them when calling it:
sayHello(String name, String additionalMessage) => "Hello $name. $additionalMessage";
  • Optional positional parameters: Sometimes, not all parameters need to be mandatory for a function, so it can define optional parameters as well. The optional positional parameter definition is done by using the [ ] syntax. Optional positional parameters must go after all of the required parameters, as follows:
sayHello(String name, [String additionalMessage]) => "Hello $name. $additionalMessage";

If you run the preceding code without passing a value for additionalMessage, you will see null at the end of the returned string. When the optional parameter is not specified, the default value is null unless you specify default values for them:

void main() {
print(sayHello('my friend')); // Hello my friend. null
print(sayHello('my friend', "How are you?"));
// prints Hello my friend. How are you?
}

To define a default value for a parameter, you add it after the = sign right after the parameter definition:

sayHello(String name, [String additionalMessage = "Welcome to Dart Functions!" ]) => "Hello $name. $additionalMessage";

Not specifying the parameter results in printing the default message, as follows:

void main() {
var hello = sayHello('my friend');
print(hello);
}
  • Optional named parametersThe optional named parameter definition is done by using the { } syntax. They must also go after all of the required parameters:
sayHello(String name, {String additionalMessage}) => "Hello $name. $additionalMessage";

The caller must specify the name of the optional named parameter, as follows:

void main() {
print(sayHello('my friend'));
// it stills optional, prints: Hello my friend. null

print(sayHello('my friend', additionalMessage: "How are you?"));
// prints: Hello my friend. How are you?
}

Named parameters are not exclusive to optional parameters; to make a named parameter a required parameter, you can mark it with @required:

sayHello(String name, {@required String additionalMessage}) => "Hello $name. $additionalMessage";

Again, the caller must specify the name of the required named parameter:

void main() {
var hello = sayHello('my friend', additionalMessage:"How are
you?");
// not specifying the parameter name will result in a hint on
// the editor, or by running dartanalyzer manually on console

print(hello); // prints "Hello my friend. How are you?"
}
  • Anonymous functions: Dart functions are objects and they can be passed as parameters to other functions. We already saw this when using the forEach() function of the iterable.

An anonymous function is a function that doesn't have a name; it is also called lambda or closureThe  forEach() function is a good example of this; we need to pass a function to it that will be executed with each of the list collection elements:

void main() {
var list = [1, 2, 3, 4];
list.forEach((number) => print('hello $number'));
}

Our anonymous function receives an item but does not specify a type; then, it just prints the value received by the parameter.

  • Lexical scope: The Dart scope is determined by the layout of the code using curly braces like many programming languages; the inner functions can access variables all the way up to the global level:
globalFunction() {
print("global/top-level function");
}

simpleFunction() {
print("simple function");
globalFunction() {
print("Not really global");
}

globalFunction();
}

main() {
simpleFunction();

globalFunction();
}

If you examine the preceding code, globalFunction function from simpleFunction will be used instead of the global version, because it is defined locally on its scope.

In the main function, in contrast, the global version of globalFunction function is used, because, in this scope, the internal globalFunction function from simpleFunction is not defined.