Reputation: 280
I'm new to Dart and tried to get a class to implement List
using the answers here, and tried to sort a list of these objects using the docs here. I deleted most of my code in an effort to post a MWE:
import 'dart:collection';
class Transaction<E> extends ListBase<E>{
DateTime when;
Transaction(this.when);
List innerList = new List();
int get length => innerList.length;
void set length(int length){
innerList.length = length;
}
void operator[]=(int index, E value){
innerList[index] = value;
}
E operator [](int index) => innerList[index];
void add(E value) => innerList.add(value);
void addAll(Iterable<E> all) => innerList.addAll(all);
}
class Forecaster{
var transactions;
Forecaster(){
this.transactions = new List<dynamic>();
}
void tabulate(){
transactions.sort((a,b) => a.when.compareTo(b.when)); //problem line?
for(var d in transactions){
d.asMap().forEach((index,content){
int len = content.toStringAsFixed(2).length;
});
}
}
void forecast(var forWhen){
var first = new Transaction(DateTime.now());
first.addAll([5,9]);
transactions.add(first);
}
}
void main(){
Forecaster myTest = new Forecaster();
var dub = myTest;
dub..forecast(DateTime.now())
..tabulate();
}
Running with the problem line results in an exception (Uncaught exception: TypeError: Closure 'Forecaster_tabulate_closure': type '(dynamic, dynamic) => dynamic' is not a subtype of type '(dynamic, dynamic) => int') I don't understand. If I comment out the problem line, the TypeError
goes away. Is the TypeError
because I did something wrong when defining Transaction
? I'm attempting this with DartPad.
Upvotes: 0
Views: 103
Reputation: 71793
Your problem is with the types. The code:
var transactions;
Forecaster(){
this.transactions = new List<dynamic>();
}
void tabulate(){
transactions.sort((a,b) => a.when.compareTo(b.when));
first declares transactions
to have type dynamic
.
Then you call sort
on that with an argument which is inferred to have type dynamic Function(dynamic, dynamic)
(because there is no clue available to say otherwise in the type of transactions
).
However, the actual run-time type of transactions
is List<Transaction>
, and that requires a function argument of type int Function(Transaction, Transaction)
. The type dynamic Function(dynamic, dynamic)
is not a sub-type of int Function(Transaction, Transaction)
(the return type has to be a subtype of int
for that to be the case) so you get a run-time error.
If you change transactions
to have type List<Transaction>
, then the type inference will have a clue when it gets to the function literal. It will infer that (a, b) => a.when.compareTo(b.when)
in a context expecting int Function(Transaction, Transaction)
will have that type.
Even if you just change transactions
to List<dynamic>
, it will still work, it will just make a.when.compareTo(b.when)
be dynamic invocations.
Upvotes: 1
Reputation: 2599
I'm new to Dart too, so my explanation might not be 100% on the money, but I believe, yes, the main issue is the type assignment of transactions
. I think because you initialize it as a var, it is having trouble deducing the type of a.when
, which is means it also doesn't know the type of a.when.compareTo()
, and assumes dynamic
. You are feeding the output of compareTo
into List.sort()
which is expecting an int
from the anonymous function. Thus the error that it wanted an int
but got dynamic
.
The easiest way to address this is to initialize transactions with a more explicit type rather than as var:
List<Transaction> transactions;
Forecaster(){
this.transactions = new List<Transaction>();
}
Also, to confirm that it is an issue with it not being able to infer the return type of compareTo, I tried leaving your code as-is, but explicitly casting the result as int, and that also worked:
transactions.sort((a,b){
return (a.when.compareTo(b.when) as int);
});
Note: code like the above and using lots of dynamics and vars is in general not great practice with Dart - you lose a lot of the benefits of having a typed language. You might also notice that when you type in an IDE, you don't get methods auto-suggested when you do stuff like this - for example, until I changed transactions
to an explicit type of list, typing a.when
did not trigger autocomplete, and my IDE thought the type was dynamic
, not DateTime
.
Upvotes: 2