flutterdartparametersnamed-parameterspositional-parameter

What is the difference between named and positional parameters in Dart?


Dart supports both named optional parameters and positional optional parameters. What are the differences between the two?

Also, how can you tell if an optional parameter was actually specified?


Solution

  • Dart has two types of optional parameters: named and positional. Before I discuss the differences, let me first discuss the similarities.

    Dart's optional parameters are optional in that the caller isn't required to specify a value for the parameter when calling the function.

    Optional parameters can only be declared after any required parameters.

    Optional parameters can have a default value, which is used when a caller does not specify a value.

    Positional optional parameters

    A parameter wrapped by [ ] is a positional optional parameter. Here is an example:

    getHttpUrl(String server, String path, [int port=80]) {
      // ...
    }
    

    In the above code, port is optional and has a default value of 80.

    You can call getHttpUrl with or without the third parameter.

    getHttpUrl('example.com', '/index.html', 8080); // port == 8080
    getHttpUrl('example.com', '/index.html');       // port == 80
    

    You can specify multiple positional parameters for a function:

    getHttpUrl(String server, String path, [int port=80, int numRetries=3]) {
      // ...
    }
    

    The optional parameters are positional in that you can't omit port if you want to specify numRetries.

    getHttpUrl('example.com', '/index.html');
    getHttpUrl('example.com', '/index.html', 8080);
    getHttpUrl('example.com', '/index.html', 8080, 5);
    

    Of course, unless you know what 8080 and 5 are, it's hard to tell what those apparently magic numbers are. You can use named optional parameters to create more readable APIs.

    Named optional parameters

    A parameter wrapped by { } is a named optional parameter. Here is an example:

    getHttpUrl(String server, String path, {int port = 80}) {
      // ...
    }
    

    You can call getHttpUrl with or without the third parameter. You must use the parameter name when calling the function.

    getHttpUrl('example.com', '/index.html', port: 8080); // port == 8080
    getHttpUrl('example.com', '/index.html');             // port == 80
    

    You can specify multiple named parameters for a function:

    getHttpUrl(String server, String path, {int port = 80, int numRetries = 3}) {
      // ...
    }
    

    Because named parameters are referenced by name, they can be used in an order different from their declaration.

    getHttpUrl('example.com', '/index.html');
    getHttpUrl('example.com', '/index.html', port: 8080);
    getHttpUrl('example.com', '/index.html', port: 8080, numRetries: 5);
    getHttpUrl('example.com', '/index.html', numRetries: 5, port: 8080);
    getHttpUrl('example.com', '/index.html', numRetries: 5);
    

    I believe named parameters make for easier-to-understand call sites, especially when there are boolean flags or out-of-context numbers.

    Checking if optional parameter was provided

    Unfortunately, you cannot distinguish between the cases "an optional parameter was not provided" and "an optional parameter was provided with the default value".

    Note: You may use positional optional parameters or named optional parameters, but not both in the same function or method. The following is not allowed.

    thisFunctionWontWork(String foo, [String positonal], {String named}) {
      // will not work!
    }