Appearance
Function abstract final
abstract final class FunctionA function value.
The Function class is a supertype of all function types, and contains no values itself. All objects that implement Function have a function type as their runtime type.
The Function type does not carry information about the parameter signatures or return type of a function. To express a more precise function type, use the function type syntax, which is the Function keyword followed by a parameter list, or a type argument list and a parameter list, and which can also have an optional return type.
The function type syntax mirrors the definition of a function, with the function name replaced by the word "Function".
Example:
dart
String numberToString(int n) => "$n";
String Function(int n) fun = numberToString; // Type annotation
assert(fun is String Function(int)); // Type check.
List<String Function(int)> functions = [fun]; // Type argument.The type String Function(int) is the type of a function that takes one positional int argument and returns a String.
Example with generic function type:
dart
T id<T>(T value) => value;
X Function<X>(X) anotherId = id; // Parameter name may be omitted.
int Function(int) intId = id<int>;A function type can be used anywhere a type is allowed, and is often used for functions taking other functions, "callbacks", as arguments.
dart
void doSomething(String Function(int) callback) {
print(callback(1));
}A function type has all the members declared by Object, since function types are subtypes of Object.
A function type also has a call method with a signature that has the same function type as the function type itself. Calling the call method behaves just as calling the function. This is mainly used to conditionally call a nullable function value.
dart
String Function(int) fun = (n) => "$n";
String Function(int) fun2 = fun.call; // Valid.
print(fun2.call(1)); // Prints "1".
String Function(int)? maybeFun = Random().nextBool() ? fun : null;
print(maybeFun?.call(1)); // Prints "1" or "null".The Function type has a number of special features which are not visible in this class declaration.
The Function type itself allows any function to be assigned to it, since it is a supertype of any function type, but does not say how the function can be called.
However, a value with the static type Function can still be called like a function.
dart
Function f = (int x) => "$x";
print(f(1)); // Prints "1".
f("not", "one", "int"); // Throws! No static warning.Such an invocation is a dynamic invocation, precisely as if the function value had been statically typed as dynamic, and is precisely as unsafe as any other dynamic invocation. Checks will be performed at run-time to ensure that the argument list matches the function's parameters, and if not the call will fail with an Error. There is no static type checking for such a call, any argument list is accepted and checked at runtime.
Like every function type has a call method with its own function type, the Function type has a special call member which acts as if it is a method with a function type of Function (which is not a method signature which can be expressed in normal Dart code).
dart
Function fun = (int x) => "$x";
var fun2 = fun.call; // Inferred type of `fun2` is `Function`.
print(fun2.call(1)); // Prints "1";
Function? maybeFun = Random().nextBool() ? fun : null;
print(maybeFun?.call(1)); // Prints "1" or "null".Available Extensions
Properties
hashCode no setter override
int get hashCodeA hash code value that is compatible with operator==.
Implementation
dart
int get hashCode;runtimeType no setter inherited
Type get runtimeTypeA representation of the runtime type of the object.
Inherited from Object.
Implementation
dart
external Type get runtimeType;toJS extension no setter
JSExportedDartFunction get toJSA callable JavaScript function that wraps this Function.
If the static type of the Function could not be determined or if the static type uses types that are disallowed, the call will fail to compile. See https://dart.dev/interop/js-interop/js-types#requirements-on-external-declarations-and-function-tojs for more details on what types are allowed.
The max number of arguments that are passed to this Function from the wrapper JavaScript function is determined by this Function's static type. Any extra arguments passed to the JavaScript function after the max number of arguments are discarded like they are with regular JavaScript functions.
Calling this on the same Function again will always result in a new JavaScript function.
Available on Function, provided by the FunctionToJSExportedDartFunction extension
Implementation
dart
external JSExportedDartFunction get toJS;toJSCaptureThis extension no setter
JSExportedDartFunction get toJSCaptureThisA callable JavaScript function that wraps this Function and captures the this value when called.
Identical to toJS, except the resulting JSExportedDartFunction will pass this from JavaScript as the first argument to the converted Function. Any Function that is converted with this member should take in an extra parameter at the beginning of the parameter list to handle this.
Available on Function, provided by the FunctionToJSExportedDartFunction extension
Implementation
dart
@Since('3.6')
external JSExportedDartFunction get toJSCaptureThis;Methods
noSuchMethod() inherited
dynamic noSuchMethod(Invocation invocation)Invoked when a nonexistent method or property is accessed.
A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:
dart
dynamic object = 1;
object.add(42); // Statically allowed, run-time errorThis invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).
Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.
A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:
dart
class MockList<T> implements List<T> {
noSuchMethod(Invocation invocation) {
log(invocation);
super.noSuchMethod(invocation); // Will throw.
}
}
void main() {
MockList().add(42);
}This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.
If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError.
Inherited from Object.
Implementation
dart
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);toString() inherited
String toString()A string representation of this object.
Some classes have a default textual representation, often paired with a static parse function (like int.parse). These classes will provide the textual representation as their string representation.
Other classes have no meaningful textual representation that a program will care about. Such classes will typically override toString to provide useful information when inspecting the object, mainly for debugging or logging.
Inherited from Object.
Implementation
dart
external String toString();Operators
operator ==() override
Test whether another object is equal to this function.
Function objects are only equal to other function objects (an object satisfying object is Function), and never to non-function objects.
Some function objects are considered equal by == because they are recognized as representing the "same function":
It is the same object. Static and top-level functions are compile time constants when used as values, so referring to the same function twice always yields the same object, as does referring to a local function declaration twice in the same scope where it was declared.
dartvoid main() { assert(identical(print, print)); int add(int x, int y) => x + y; assert(identical(add, add)); }The functions are same member method extracted from the same object. Repeatedly extracting ("tearing off") the same instance method of the same object to a function value gives equal, but not necessarily identical, function values.
dartvar o = Object(); assert(o.toString == o.toString);Instantiations of equal generic functions with the same types yields equal results.
dartT id<T>(T value) => value; assert(id<int> == id<int>);
(If the function is a constant and the type arguments are known at compile-time, the results may also be identical.)
Different evaluations of function literals are not guaranteed or required to give rise to identical or equal function objects. For example:
dart
var functions = <Function>[];
for (var i = 0; i < 2; i++) {
functions.add((x) => x);
}
print(identical(functions[0], functions[1])); // 'true' or 'false'
print(functions[0] == functions[1]); // 'true' or 'false'If the distinct values are identical, they are always equal.
If the function values are equal, they are guaranteed to behave indistinguishably for all arguments.
If two functions values behave differently, they are never equal or identical.
The reason to not require a specific equality or identity of the values of a function expression is to allow compiler optimizations. If a function expression does not depend on surrounding variables, an implementation can safely be shared between multiple evaluations. For example:
dart
List<int> ints = [6, 2, 5, 1, 4, 3];
ints.sort((x, y) => x - y);
print(ints);A compiler can convert the closure (x, y) => x - y into a top-level function.
Implementation
dart
bool operator ==(Object other);Static Methods
apply()
dynamic apply(
Function function,
List<dynamic>? positionalArguments, [
Map<Symbol, dynamic>? namedArguments,
])Dynamically call function with the specified arguments.
Acts the same as dynamically calling function with positional arguments corresponding to the elements of positionalArguments and named arguments corresponding to the elements of namedArguments.
This includes giving the same errors if function expects different parameters.
Example:
dart
void printWineDetails(int vintage, {String? country, String? name}) {
print('Name: $name, Country: $country, Vintage: $vintage');
}
void main() {
Function.apply(
printWineDetails, [2018], {#country: 'USA', #name: 'Dominus Estate'});
}
// Output of the example is:
// Name: Dominus Estate, Country: USA, Vintage: 2018If positionalArguments is null, it's considered an empty list. If namedArguments is omitted or null, it is considered an empty map.
dart
void helloWorld() {
print('Hello world!');
}
void main() {
Function.apply(helloWorld, null);
}
// Output of the example is:
// Hello world!Implementation
dart
external static apply(
Function function,
List<dynamic>? positionalArguments, [
Map<Symbol, dynamic>? namedArguments,
]);