簡體   English   中英

Scala可堆疊特征和自我類型不兼容類型

[英]Scala Stackable Trait and Self Type Incompatible Type

我有一個名為Mutatable的特性,它會吐出一個實現類的修改后的副本。 我還有一個特性,我想在它上面堆疊,稱為CostedMutatable,它跟蹤這樣做的成本。 applyMutation方法返回一個Option,后面我想在特定的變異不適用的情況下返回None。

一個簡單的版本只適用於Ints(並通過添加新數字“變異”它們)如下所示:

trait Mutatable[M] {

  def applyMutation(mut : M) : Option[this.type]
}

trait CostedMutatable[M] extends Mutatable[M]{

  var cost : Int = _
  def getCostFor(mut : M): Int

  abstract override def applyMutation(mut : M) : Option[this.type] = {
    cost += getCostFor(mut)
    applyMutation(mut)
  }
}

object Example extends App {

  case class Mutation(x: Int)

  class Test(s: Int) extends Mutatable[Mutation] {
    val start = s
    override def applyMutation(mut: Mutation): Option[Test] 
         = Some(new Test(s+mut.x))
  }

  class CostTest(s: Int) extends Test(s) with CostedMutatable[Mutation] {
    override def getCostFor(mut: Mutation): Int = 2
  }

  val testCost = new CostTest(5).cost
}

問題是,這不會編譯。 我在編譯時遇到以下錯誤:

Error:(23, 18) overriding method applyMutation in trait Mutatable of type (mut: Example.Mutation)Option[Test.this.type];
 method applyMutation has incompatible type
    override def applyMutation(mut: Mutation): Option[Test] = Some(new Test(s+mut.x))
                 ^

除了編譯器錯誤之外,還會想到另一個問題:我是否正確地接近這個問題? 我應該使用F-bounded類型嗎? (我需要每個新的實現類從applyMutation返回具體實現類的新副本。)

提前致謝。

this.type是一個類型,其唯一的實例是thisNothing 當方法返回this.type ,唯一允許的返回值是this 在類Test applyMutation不返回this ,而是一個全新的Test ,它不是this.type的實例。 這就是代碼不進行類型檢查的原因。

我覺得你真正要做的是宣布applyMutation返回同一類值this 這樣做確實需要F-Bounded多態性。 這是您的代碼的重寫版本:

trait CostedMutatable[+A <: CostedMutatable[A, M], M] extends Mutatable[A, M] {

  var cost : Int = _
  def getCostFor(mut : M): Int

  abstract override def applyMutation(mut: M): Option[A] = {
    cost += getCostFor(mut)
    super.applyMutation(mut)
  }
}

object Example extends App {

  case class Mutation(x: Int)

  class Test(s: Int) extends Mutatable[Test, Mutation] {
    val start = s
    override def applyMutation(mut: Mutation): Option[Test] 
         = Some(new Test(s+mut.x))
  }

  class CostTest(s: Int) extends Test(s) with CostedMutatable[CostTest, Mutation] {
    override def getCostFor(mut: Mutation): Int = 2
  }

  val testCost = new CostTest(5).cost
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM