The function is a first-class citizen

A first class citizen is just a term for the highest rank. In OC, the class is the first citizen, so we can treat the object created by the class as a parameter or return value. Functions are first citizens in Dart, so they can be used as arguments or return values

Pass the function as an argument
  • Since functions are the highest level, we can declare the parameter type to be a function when passing a parameter and pass a function when calling
Void test(Function foo){print(" call test1"); void test(Function foo){print(" call test1"); var result = foo("lilei"); print("test.result $result"); } String bar([String name]){ print("name $name"); return name; }Copy the code

Here we declare test as a Function of type Function, so we can pass in a Function bar as an argument

// Since the function is a first-class citizen, we can pass the function directly as an argument to test(bar);Copy the code

When called in test, foo is the bar function. Calling foo(“lilei”) calls bar with a string lilei, and bar returns a string value

Print the result

Call test name lilei test.result LILeiCopy the code

Through log, we can find that bar is passed to test as a function, and the call of bar is realized in test. Note that when calling function parameters in test, the pass value must match bar, and also pay attention to the transfer of mandatory and optional parameters. Refer to the basic usage of functions for mandatory and optional parameters

The above method of calling, when the function is passed as a parameter, also needs to declare a function bar, which is time-consuming in development, so this is where anonymous functions appear

Anonymous functions

Anonymous functions do not need to be declared separately, just declare the function when passing the parameter

First we declare a test

Void test1(Function foo){print(" call test"); var result = foo(); print("test.result $result"); }Copy the code

When we pass in the function test, we implement the function declaration directly in the argument

Test1 (([int value = 1]){print(" call anonymous function "); return value*2; });Copy the code

Print the result

Call test1 call the anonymous function test1.result 20Copy the code

So if we log an anonymous function we’ll call it foo1 for short, we’ll call test1 first, and in test1 we log foo(10), which corresponds to the anonymous function foo1, so we call foo1 and we pass in 10, so we call foo1 and we call our anonymous function and we pass in 10, So log “call an anonymous function” and return value*2, return 20 to result in test1, and then print result 20

  • There is no difference in implementation between an anonymous function and declaring a function as a parameter. The only difference is that the function is declared directly in the parameter without the step of declaring the parameter function separately

Arrow anonymous function

Arrow anonymous function is a kind of anonymous function, belonging to a shorthand of anonymous function, but requires that the function body can only have one line of code

Test (() =>print(" arrow function called ")); Test (()=>{print(" arrow function ")}); print(" arrow function ") =>{print(" arrow function ");Copy the code

The log is printed when the parameter function is called in test

The arrow function can only have one line of code body but we can implement complex event responses by executing other functions in the code body

Test (()=>bar(" arrow function 1"); // We can do this by calling other functions hereCopy the code
In the above code, we declare the test Function as a Function foo. At this time, we do not specify the format of foo. We can determine the format type of foo by declaring the test Function

Determines the format for declaring parameter functions

Foo (num1, num2); // Foo (num1, num2); Void test2(int foo(int num1, int num2)){int result = foo(10,20); print("test2.result $result"); }Copy the code

When called, the parameter function must follow this format. It contains two mandatory parameters of int type and returns a value of int type. In this case, we pass the parameter as an anonymous function for easier observation

test2(( num1, num2){
      return num1*num2;
  });
Copy the code

The above declaration is not good enough for code readability, so we can convention foo’s format by splitting it

// Typepedef FooText = int Function(int num1,int num2); // Typef FooText = int Function(int num1,int num2); Void test3(FooText foo){int result = foo(10,20); print("test3.result $result"); }Copy the code

Here we declare a function FooText and its format. In the test3 argument, we declare a function foo directly with FooTest. The format of foo contains two mandatory ints and returns a value of int

  test3((num1,num2){
    return num1*num2;
  });
Copy the code

Treat the function as a return value

Since functions are first-class citizens, we can also return a function when a function returns a value

Function test4(){
  return (int num1, String num2){
    return num1*int.parse(num2);
  };
}
Copy the code

Call test4

  var foo = test4();
  print("foo $foo ${foo.runtimeType}");
Copy the code

Print the result

foo Closure: (int, String) => int (int, String) => int
Copy the code

Test4 () returns two required arguments int and sring, and returns an argument of type int. We can then call foo to return this argument

var value = foo(10,"20"); print("valur $value"); Parse (num2); // return num1*int. Parse (num2); / /}; The function ofCopy the code

Print the result

value 200
Copy the code

Here we define Function as a Function, and also define the type of Function returned in more detail

typedef FooText = int Function(int num1,int num2); Return (num1,num2){return num1*num2; FooText test5(){return num1*num2; }; }Copy the code

This is called in the same way as test4

var fooTextClassFoo = test5(); print("fooTextClassFoo $fooTextClassFoo ${fooTextClassFoo.runtimeType}"); Var value1 = fooTextClassFoo (20, 30); print("value1 $value1");Copy the code

Print the result

fooTextClassFoo Closure: (int, int) => int (int, int) => int
value1 600
Copy the code