【问题标题】:correct type specification for cloneable-like trait in scalascala中可克隆特征的正确类型规范
【发布时间】:2013-08-23 01:09:04
【问题描述】:

问题不是关于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 的类是不同的。然后后代应该重写 clone 方法以匹配它自己的类型。

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

我查看了 scala 集合并在此处找到提示:定义处理类型限制的 TestLike 特征和体现相应特征的类 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 的问题在于类型系统忽略了SubStore 类中缺少的clone() 方法,尽管SubStore 是Cloneable 的后代,通过Store。但是带有类型参数Store 的Store finalize Cloneable 接口及其所有后代都缺乏适当的clone() 方法限制

【问题讨论】:

  • 不是很漂亮,但 Scala 的 C++ 版本“CRTP”(奇怪的是重复出现的模板模式):trait Cloneable[A :&lt; Cloneable[A]] { def clone(): A }。
  • 我在应用循环模板模式时遇到了问题,并将其发布在更新的任务中
  • class Store extends Cloneable[Store], override def clone(): Store
  • 用新问题更新问题
  • 在你上一个代码 sn-p override def clone() : A = new Store[A](store) 中,A 是从哪里来的?并且 Store 不接受类型参数。什么是过早完成?

标签: scala inheritance static-typing


【解决方案1】:

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)) 会编译。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2013-06-09
    • 2015-05-26
    相关资源
    最近更新 更多