【问题标题】:Dart typecasting errorDart 类型转换错误
【发布时间】:2013-12-31 15:47:06
【问题描述】:

我有一个抽象类Event 和一个扩展它的具体子类PlaceChangeEvent。在事件侦听器中,我有以下代码:

void onEvent(Event event) {
    PlaceChangeEvent pce = null;
    if(event is PlaceChangeEvent)
        pce = (PlaceChangeEvent)event;      // <== error is here
    else
        throw new Exception("Event is not a PlaceChangeEvent.");

    Place place = pce.place;

    presenterProvider.display(place);
}

所以如果event 的运行时类型是PlaceChangeEvent,那么我需要将事件转换为该类型,以便我可以访问它的属性。但是我在类型转换上遇到编译器错误,说明:

“Type”类型的值不能分配给“PlaceChangeEvent”类型的变量

我哪里出错了,我需要做些什么来解决它?

【问题讨论】:

    标签: casting dart


    【解决方案1】:

    飞镖

    1. 上播是隐式的。如果BA 的子类,那么B b = a(其中aA 类的一个实例)是无警告的,并且默默地将a 强制转换为B。在 Java 中,您需要编写 B b = (B) a

    2. 动态类型是一个始终存在的逃生舱口。如果BC 不在同一层次结构中,则临时分配给动态类型将使强制转换无警告。

      B b = someB;
      var tmp = b;
      C c = tmp;
      
    3. 可以使用is 进行显式检查。如果对象的类型正确,is 检查将返回 true。还有一些非常简单的规则可以传播 is-check 类型。例如,如果在if 条件中使用is,则相应的分支会将此信息用于类型警告。

      Object o;
      o.foo();  // warning: foo does not exist on Object.
      if (o is A) {  // assuming that A contains 'foo'.
        o.foo();  // warning-free.
      }
      
    4. 如果类型不是as 的预期类型,则可以显式检查并抛出。当左侧为null 时,此运算符抛出。

    对于您的示例,这归结为:

    没有明确的检查(1):

    void onEvent(Event event) {
      // Implicit upcast. PlaceChangeEvent is subclass of Event.
      PlaceChangeEvent pce = event;
      Place place = pce.place;
      presenterProvider.display(place);
    }
    

    使用 is-check (3):

    void onEvent(Event event) {
      if (event is PlaceChangeEvent) {
        // Static type system propagates type. No need for variable.
        Place place = event.place;
        presenterProvider.display(place);
      } else {
        // Note: this doesn't look like an exception, but an error.
        throw new Exception("Event is not a PlaceChangeEvent.");
      }
    }
    

    使用as (4):

    void onEvent(Event event) {
      Place place = (event as PlaceChangeEvent).place;
      presenterProvider.display(place);
    }
    

    或者,如果您希望收到 PlaceChangeEvent,您只需更改参数的类型:

    void onEvent(PlaceChangeEvent event) {
      Place place = event.place;
      presenterProvider.display(place);
    }
    

    在检查模式下,这将捕获错误类型,在未检查模式下,它会在访问event.place 时抛出。这通常是首选方式。

    【讨论】:

      【解决方案2】:

      试试这个:

      pce = event as PlaceChangeEvent;
      

      【讨论】:

      • 感谢@ringstaff (+1) - 但是如果event 的运行时类型是Event 的另一个子类除了 PlaceChangeEvent 怎么办?假设我有另一个名为LogEvent 的子类,而在运行时event 实际上是LogEvent(不是PlaceChangeEvent)?演员会怎样?
      • 再次感谢@ringstaff (+1) - 一般来说,如果 as 演员表失败,Dart 会发生什么?是否抛出异常,如果是,是什么类型?再次感谢!
      • @CalifornianAcorn - 如果案例失败,它将抛出 TypeError 异常(类型 'Foo' 不是 'pce' 的 'PlaceChangeEvent' 类型的子类型。
      • 那时将不会执行带有强制转换的行,因为您检查事件是否只是 PlaceChangeEvent。在其他世界中,您的异常被抛出(重新发布,因为我无法编辑并且有一个大错字)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      • 2020-06-18
      • 2020-05-24
      • 1970-01-01
      相关资源
      最近更新 更多