尝试对自定义对象列表进行排序时出现TypeError

时间:2019-06-03 06:19:13

标签: dart

我是Dart的新手,它尝试使用答案here来实现List的类,并尝试使用文档here对这些对象的列表进行排序。我删除了大部分代码以发布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();
}

以问题行运行会导致异常(未捕获的异常:TypeError:闭包“ Forecaster_tabulate_closure”:类型“(动态,动态)=>动态”不是类型“(动态,动态)=> int”的子类型) )我不明白。如果我注释掉问题行,则TypeError消失。 TypeError是因为我在定义Transaction时做错了吗?我正在尝试使用DartPad

2 个答案:

答案 0 :(得分:2)

我也是Dart的新手,所以我的解释可能不是100%的花销,但我相信,是的,主要问题是transactions的类型分配。我认为,因为您将其初始化为var,所以很难推断出a.when的类型,这意味着它也不知道a.when.compareTo()的类型,并且假设dynamic。您正在将compareTo的输出输入到List.sort()中,该输出期望匿名函数提供int。因此,它想要一个int但却得到dynamic的错误。

解决此问题的最简单方法是使用更明确的类型而不是var初始化事务:

List<Transaction> transactions;
Forecaster(){
    this.transactions = new List<Transaction>();
}

此外,要确认这是一个问题,因为它无法推断compareTo的返回类型,我尝试将您的代码保持原样,但将结果显式转换为int,这也有效:

transactions.sort((a,b){
    return (a.when.compareTo(b.when) as int);
});

注意:上面的代码以及使用大量的动力学和变量通常在Dart中不是很好的做法-使用类型化语言会失去很多好处。您可能还会注意到,在键入IDE时,执行此类操作时不会自动建议使用方法-例如,直到我将transactions更改为显式类型的列表,然后键入{{1 }}没有触发自动完成,我的IDE认为类型是a.when,而不是dynamic

答案 1 :(得分:1)

您的问题在于类型。代码:

var transactions;
Forecaster(){
    this.transactions = new List<dynamic>();
}
void tabulate(){
    transactions.sort((a,b) => a.when.compareTo(b.when));

首先声明transactions具有类型dynamic。 然后,使用一个推断为sort类型的参数调用dynamic Function(dynamic, dynamic)(因为transactions类型的线索不存在)

但是,transactions的实际运行时类型为List<Transaction>,这需要类型为int Function(Transaction, Transaction)的函数参数。类型dynamic Function(dynamic, dynamic)不是int Function(Transaction, Transaction)的子类型(返回类型必须是int的子类型),因此会出现运行时错误。

如果将transactions更改为类型List<Transaction>,则类型推断将在获取函数文字时提供线索。它将推断(a, b) => a.when.compareTo(b.when) 在期望int Function(Transaction, Transaction) 的上下文中将具有该类型。

即使您仅将transactions更改为List<dynamic>,它仍然可以工作,也只会使a.when.compareTo(b.when)是动态调用。