scala中类似于cloneable的trait的正确类型规范

时间:2013-08-20 20:18:28

标签: scala inheritance static-typing

问题不在于AnyRef.clone(),而在于具有类似语义的情况。

我想为可能创建自身副本的类定义一个接口:

trait Cloneable {
  def clone() : this.type
}

class Test(val store : Int) extends Cloneable {
  def clone() = new Test(store)
}

路径相关this.type不起作用,因为this.type类类型和扩展Test的类不同Test。然后,后代应该重写克隆方法以匹配其自己的类型。

我应该如何定义Cloneable特征的类型要求?

我偷看了scala集合,在这里找到了tip:define TestLike trait,它处理类型限制,以及类Test,它体现了相应的特征。

如果可能,我想避免不必要的笨拙


按照建议尝试自我反复出现的模式:

trait Cloneable[A <: Cloneable[A]] {
  def clone() : A
}

class Store[A <: Cloneable[A]](val store : Int) extends Cloneable[A] {
  override def clone() : A = new Store[A](store)
}

因错误而失败:

Cloneable.scala:6: error: type mismatch;
 found   : Store[A]
 required: A
  override def clone() : A = new Store[A](store)

定期模板中的另一个问题:提前完成

class Store(val store : Int) extends Cloneable[Store] {
  override def clone() = new Store(store)
}

class SubStore(store : Int, val stash : Double) extends Store(store)

val ss1 = new SubStore(1, 0.5)
val ss2 = ss1.clone()
assert(ss2.isInstanceOf[SubStore])

SubStore的问题是类型系统忽略了clone()类中缺少的SubStore方法,尽管SubStoreCloneable后代通过Store }。但是Store带有类型参数Cloneable的最终Store接口及其所有后代缺少正确的clone()方法限制

1 个答案:

答案 0 :(得分:0)

Scala类型差异允许您以简单的方式实现所需,但您必须放弃继承并转到类型类。

trait Cloner[A]{
  def cloneObject(input:A):A
}
trait CloningFunctions{
  def cloneObject[A](input:A)(implicit cloner:Cloner[A]) = cloner.cloneObject(input)
}

object CloningFunctions extends CloningFunctions

class MyClass1(val b:Int)
class MyClass2(val a:Int,b:Int) extends MyClass1(b)

object Example {

  implicit val cloner = new Cloner[MyClass1]{
    def cloneObject(input: MyClass1): MyClass1 = new MyClass1(input.b)
  }

  import CloningFunctions._

  cloneObject(new MyClass2(3,4))

}

这里的想法是,由于Cloner [A]在类型A中是不变的,因此以下代码将无法编译:

无法找到参数cloner的隐含值:Cloner [MyClass2]   cloneObject(new MyClass2(3,4))

因为你有一个Cloner [MyClass1]而不是范围内的Cloner [MyClass2]。

虽然cloneObject(new MyClass1(3))会编译。