【问题标题】:TypeError while attempting to sort a list of custom objects尝试对自定义对象列表进行排序时出现 TypeError
【发布时间】:2019-10-18 16:37:44
【问题描述】:

我是 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: Closure 'Forecaster_tabulate_closure': type '(dynamic, dynamic) => dynamic' is not a subtype of type '(dynamic, dynamic) => int' ) 我不明白。如果我注释掉问题行,TypeError 就会消失。 TypeError 是不是因为我在定义 Transaction 时做错了什么?我正在尝试使用DartPad

【问题讨论】:

    标签: dart


    【解决方案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&lt;Transaction&gt;,这需要int Function(Transaction, Transaction) 类型的函数参数。 dynamic Function(dynamic, dynamic) 类型不是 int Function(Transaction, Transaction) 的子类型(返回类型必须是 int 的子类型),所以会出现运行时错误。

    如果您将transactions 更改为List&lt;Transaction&gt; 类型,则类型推断在到达函数字面量时会有线索。它将推断出(a, b) =&gt; a.when.compareTo(b.when) 在期望int Function(Transaction, Transaction) 的上下文中将具有该类型。

    即使您只是将transactions 更改为List&lt;dynamic&gt;,它仍然可以工作,它只会使a.when.compareTo(b.when) 成为动态调用。

    【讨论】:

      【解决方案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 更改为显式类型的列表,键入 a.when 没有触发自动完成,我的 IDE 认为类型是 dynamic,而不是 DateTime

      【讨论】:

        猜你喜欢
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-06
        • 2021-07-11
        • 2021-06-16
        相关资源
        最近更新 更多