Hello Everyone,
Functions as first-class objects
```
void printElements(int x) {
print(x);
}
var mylist =
print(mylist.runtimeType);
mylist.forEach(printElements);
Output: List`<int>` 1 2 3
(works perfectly fine)
**Problem occurs when i change var to List**
```
List mylist = <int>[1, 2, 3];
print(mylist.runtimeType); //runtimeType is still the same List<int>
mylist.forEach(printElements); //now this statement is giving Error.
Error: The function 'printElements' has type 'void Function(int)' that isn't of expected type 'void Function(dynamic)'. This means its parameter or return type doesn't match what is expected
I don't know why this statement is giving error when the runtimeType is same in both the cases.
Thanks and regards,
Amit Verma
Dart has a static type system, so every variable has a static type, that is known by the compiler.
Every object also has a runtimeType, which is the actual type of this object at runtime, and this may be a more specific type.
What you are doing here is basically this:
class Animal{}
class Cat extends Animal{
void meow(){}
}
void main(){
Animal animal = Cat();
print(animal.runtimeType); // prints Cat
animal.meow(); // fails, because the static type of animal is Animal, not cat
}
By writing
List mylist = <int>[1, 2, 3];
The static type of mylist is set to List<dynamic>.
Even if the type of the right-hand side would be inferred toList<int>, you specify the type explicitly, which overwrites the type inference. Just List without generic type parameter is shorthand for List<dynamic>, which is a more general type than List<int>.
But your function
void printElements(int x) {
print(x);
}
can only take parameters of type int, not type dynamic! So because the static type of your variable is List<dynamic>, the function passed to forEach must have a signature of void Function(dynamic) but it has a signature of void Function(int).
You can fix this error either by specifying the correct type of the variable:
List<int> mylist = <int>[1, 2, 3];
or by letting the compiler figure out the correct type by itself:
var mylist = <int>[1, 2, 3];
@knaeckeKami Thanks a ton for explaining so deeply. Sorry i am still new in my dart-flutter journey. So, i was't aware of this thing..
Thanks again..
Amit
The implicit dynamic is known to be a sharp edge to the language, and predates some of the inference ideas (it certainly seems logical that if var a = [1, 2, 3] has an inferred static type of List<int>, then List a = [1, 2, 3] would have an inferred static type of List<int> as well). There are some analysis options that can help out:
In analysis_options.yaml you can specify:
analyzer:
language:
strict-raw-types: true
I think also the linter rule: always_specify_types will warn you.
Most helpful comment
The implicit
dynamicis known to be a sharp edge to the language, and predates some of the inference ideas (it certainly seems logical that ifvar a = [1, 2, 3]has an inferred static type ofList<int>, thenList a = [1, 2, 3]would have an inferred static type ofList<int>as well). There are some analysis options that can help out:In
analysis_options.yamlyou can specify:I think also the linter rule: always_specify_types will warn you.