在Scala函数中修改继承的特征

时间:2015-09-08 22:09:16

标签: scala inheritance

我正在尝试修改扩展Enterprise类型的StarShip特征。

(我提前道歉,因为我不知道这个标题的正确名称,但我会在理解答案后更新它。)

由于某种原因,我无法获得传递的starShip参数。 我评论了我收到错误的地方。

简单示例来证明这一点:

object Test {

  trait Akira extends StarShip

  trait Enterprise extends StarShip

  sealed trait StarShip {
    val captain: String
  }

  def doSomething[T: StarShip](starShip: T): T =
    new T {
       val captain = starShip.captain // Error: Cannot resolve symbol
    }

  doSomething(new Enterprise {
    override val captain = "Picard"
  })
}

由于我传递了Enterprise的对象,我希望得到同一个课程。

编辑: 刚刚意识到我希望传递的starShip中的所有变量都被复制到新类中。除了我将修改其中的一些。

我相信Monocle lib可以解决我的问题。

1 个答案:

答案 0 :(得分:0)

当我使用scala REPL编译代码时,我得到了这个:

<console>:17: error: Test.StarShip does not take type parameters
     def doSomething[T: StarShip](starShip: T): T =
                          ^
<console>:18: error: class type required but T found
       new T {
               ^
<console>:19: error: value captain is not a member of type parameter T
          val captain = starShip.captain // Error: Cannot resolve symbol
                                     ^
<console>:18: error: type mismatch;
 found   : T{}
 required: T
           new T {
           ^

正如@dcastro所提到的,你可能想要在T上绑定一个类型。但是,即使修复语法错误也不够好,因为:

scala> def doSomething[T <: StarShip](starShip : T) : T = new T { val captain = starShip.captain }
<console>:8: error: class type required but T found

无法从类型参数实例化对象,因为编译器在运行时不知道要实例化的实际类型。它可以是任何东西,包括在编译此函数后编写的类型。

根据您对doSomething的调用,我认为您根本不需要类型参数或实例化。也就是说,这有效:

scala> def doSomething[T <: StarShip](starShip : T) : T = { val captain = starShip.captain; starShip }
doSomething: [T <: StarShip](starShip: T)T

scala> doSomething(new Enterprise { val captain = "Kirk" })
res0: Enterprise = $anon$1@26653222

所以,我认为通过上述调整,你已经实现了目标。您已通过为企业提供船长成员的覆盖值来修改您的特征(StarShip)。