“This is the 20th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

preface

In Dart, functions are also objects, so they can be passed or used as normal variables at any time. The difference is that functions can take parameters, and Dart also has lambda functions. When using functions, we also need to follow certain specifications to make our code easier to read.

Specification 1: For named functions, use declarations

In modern programming languages, it is easy to create anonymous functions, such as the use of closures. Other functions can also be defined inside functions to implement nested calls. In most cases this approach is suitable for immediate callbacks. However, if a function needs to be named, it should be declared, not assigned. For example:

// Correct example
void main() {
  voidlocalFunction() { ... }}Error Example 1
void main() {
  var localFunction = () {
    ...
  };
}

// Error Example 2
void main() {
  var localFunction = () => something;
}
Copy the code

Specification 2: Pass functions as arguments instead of creating lambda functions

In some cases, we need to call another function within a function to process an object. The usual way to do this is to create a lambda. But if the called function is already defined, don’t create a lambda function because Dart provides a way to pass the function as an argument. If it sounds a little loopy, let’s look at an example where we want to loop through an array of names. Dart allows you to pass the print method to forEach each element directly.

var names = ['Bobby'.'Jack'.'Rose'];
// Correct example
name.forEach(print);

// Error example
name.forEach((name) {
  print(name);
});
Copy the code

Specification 3: Use the = operator to set default values for named parameters

Dart functions support named parameters, which are defined as follows:

void someFunction(Object item, {required int a, int b = 0.Object? c}) {
  ...
}
Copy the code

The first parameter item is a non-named parameter, the second parameter a is a mandatory named parameter, the third parameter B is a non-mandatory parameter (with a default value), and the fourth parameter is a nullable parameter (optional or null). Dart supports using colons to set defaults, but not recommended:

// Error example
void someFunction(Object item, {required int a, int b: 0.Object? c}) {
  ...
}
Copy the code

Specification 4: Type declarations precede parameters instead of using colons to declare types

In fact, this is a mistake, but also an accidental discovery. Some languages, such as Swift and Kotlin, place type declarations after parameters.

/ / swift function
func sayHello(name: String) -> Void {
  print( "Hello, \(name)");
}
Copy the code
/ / Kotlin function
fun sayHello(name: String) {
  println("Hello, $name");
}
Copy the code

Initially, if you switch from these two languages to Dart, you might write similarly, and Dart doesn’t report errors!

void sayHello({name: String{})print('Hello, $name');
}
Copy the code

That works, too. How does that work? In fact, in Dart, all types are also objects, so in the code above, name is actually of type Dynamic, except that the initial value is a String object. Let’s print it out.

void sayHello({name: String}) {
  print(name);
  print(name.runtimeType);
  print('Hello, $name');
}
sayHello();
sayHello(name: 'Jack');


/ / the result
String
Type
Hello, String
Jack
String
Hello, Jack
Copy the code

As you can see, the type changes dynamically with the parameters passed in, so this is a bad use!

Specification 5: Use function aliases wisely

Many times we can pass functions as arguments for callbacks. Using a generic Function type like Function can work, but it makes the code less readable, and declarations like Function can accept any form of callback methods, such as the following is not recommended.

// Error example
void callbackFunc({callback: Function}) {
    callback();
  }

  callbackFunc(callback: () {
    print('Hello! ');
  });
Copy the code

The correct way to do this is to set a function alias, such as VoidCallBack (ValueChanged) that comes with Flutter.

// Correct example
typedef VoidCallback = void Function(a);typedef ValueChanged = void Function<T>(T value);

void callbackFunc({callback: ValueChanged}) {
    callback('Jack');
  }

  callbackFunc(callback: (name) {
    print('Hello, $name');
  });

Copy the code

This way you know exactly what parameters and return values are required for the callback function, and your code is much more robust.

conclusion

Dart is a flexible programming language, but it can be written differently, which can lead to uneven code quality. Therefore, the development of the best reference to the official formulation of internal norms, in order to ensure the rationality of coding.

I am dao Code Farmer with the same name as my wechat official account. This is a column about the introduction and practice of Flutter, providing systematic learning articles about Flutter. See the corresponding source code here: The source code of Flutter Introduction and Practical column. If you have any questions, please add me to the wechat account: island-coder.

👍🏻 : feel the harvest please point a praise to encourage!

🌟 : Collect articles, easy to look back!

💬 : Comment exchange, mutual progress!