【问题标题】:Automatic casting in ScalaScala中的自动转换
【发布时间】:2010-02-14 01:52:47
【问题描述】:

我有一个继承 Actor 特征的类。在我的代码中,我有一个方法使用循环创建此参与者的x 数字,而另一种方法只是将 Finish 消息发送给所有参与者以告诉他们终止。我让 kill 方法只需要一个 Actor 数组,因为我希望能够将它与任何类型的 Actor 数组一起使用。但是,由于某种原因,当我将 Array[Producer] 类型的值(Producer 扩展了 Actor)传递给接受 Array[Actor] 类型的方法时,我收到了类型错误。 Scala 不应该看到 Producer 是一种 Actor 并自动转换它吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    您所描述的称为协方差,它是Scala 中大多数集合类的属性——子类型的集合是超类型集合的子类型。然而,由于Array 是一个Java 原始数组,它不是协变的——子类型的集合只是不同的。 (在 2.7 中情况更加复杂,它几乎是一个 Java 原始数组;在 2.8 中,Array 只是一个普通的 Java 原始数组,因为 2.7 的复杂性最终导致了不幸的极端情况。)

    如果您使用ArrayBuffer(来自collection.mutable List(Set 尝试相同的事情(Set 也是不变的),你会得到你想要的行为。您也可以先创建一个 Array[Actor],但始终为其提供 Producer 值。

    如果出于某种原因您确实必须使用Array[Producer],您仍然可以使用.asInstanceOf[Array[Actor]] 进行投射。但我建议使用原始数组以外的其他东西——你可能对演员做的任何事情都比使用功能更全的集合类的微小开销要慢得多。

    【讨论】:

    • 我刚刚将我的 Array 更改为 mutable.ArrayBuffer,但仍然遇到相同的转换问题。顺便说一句,我使用的是 Scala 2.7.7。
    • 但是,将集合对象切换为包含 Actor 而不是我的子类似乎已经解决了问题。
    • 哎呀——我忘记了很多 mutable 集合是不变的。不过immutable.Vector 会起作用。
    • 我应该补充一点,对于可变集合,不变性是有充分理由的。假设你有一个Array[Producer],将它传递给一个接受Array[Actor] 的函数,该函数将一些not Producers 的actor 放入其中,然后你再次使用你的数组。你以为都是Producers,其实不然!如果事情是不可变的,那么最后一步(他们改变它而你没有意识到)是不可能的,所以这不是一个问题,所以集合可以是协变的。但是对于可变集合,您的工作是使其足够广泛以开始(例如Array[Actor])。
    猜你喜欢
    • 2011-02-28
    • 2013-12-31
    • 2011-09-30
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 2020-07-30
    相关资源
    最近更新 更多