当前位置:  开发笔记 > 编程语言 > 正文

在Scala中创建现有对象类型的新实例

如何解决《在Scala中创建现有对象类型的新实例》经验,为你挑选了1个好方法。

我正在尝试基于某种具体类型的实例创建一个新实例.我有一组类型为{B,C}的类型为A类的子类型,我需要一些可调用形式的实用程序,它将采用任何现有的{B,C}实例并允许创建新实例(允许构造) )基于那种类型.

trait A

case class B(name: String) extends A

case class C(name: String) extends A

// I hoped something like this would work, but it doesn't.
def newALike[T <: A](instance: T): T = instance.copy(name = instance.name + "_new") 

所需用法:

val b = B("B")
val c = C("C")

val newB = newALike(b)
newB.name // B_new

val newC = newALike(c)
newC.name // C_new

Ben Kovitz.. 5

这将有效,但它可能需要大量重复的代码,具体取决于您的应用程序的具体情况:

trait A {
  def name: String
}

case class B(override val name: String) extends A

case class C(override val name: String) extends A

trait CanCopy[T] {
  def copy(t: T, newName: String): T
}

implicit object canCopyB extends CanCopy[B] {
  override def copy(b: B, newName: String) = b.copy(name=newName)
}

implicit object canCopyC extends CanCopy[C] {
  override def copy(c: C, newName: String) = c.copy(name=newName)
}

def newALike[T <: A](instance: T)(implicit ev: CanCopy[T]): T =
  ev.copy(instance, instance.name + "_new")

问题是特征A无法知道如何构造子类实例的具体细节.正如Scala编译器所看到的那样,没有人知道你可以定义什么作为特征A的扩展,或者它的构造函数可能采用什么参数.CanCopy和隐式对象告诉Scala编译器" 就是你如何构造一个B,就是你构造一个C的方法." 隐式参数的名称是ev,代表"证据":它告诉编译器查找可以复制类型T的证据,并且证据由可以完成工作的对象提供.

根据您的应用程序,您可以通过定义另一个特征来避免一些重复的代码,该特征扩展了A,并且B和C扩展,这可以保证.copy具有特定参数的方法可用.然后你可以有一个类型的隐式对象CanCopy[ThatIntermediaryTrait],它知道调用该.copy方法.



1> Ben Kovitz..:

这将有效,但它可能需要大量重复的代码,具体取决于您的应用程序的具体情况:

trait A {
  def name: String
}

case class B(override val name: String) extends A

case class C(override val name: String) extends A

trait CanCopy[T] {
  def copy(t: T, newName: String): T
}

implicit object canCopyB extends CanCopy[B] {
  override def copy(b: B, newName: String) = b.copy(name=newName)
}

implicit object canCopyC extends CanCopy[C] {
  override def copy(c: C, newName: String) = c.copy(name=newName)
}

def newALike[T <: A](instance: T)(implicit ev: CanCopy[T]): T =
  ev.copy(instance, instance.name + "_new")

问题是特征A无法知道如何构造子类实例的具体细节.正如Scala编译器所看到的那样,没有人知道你可以定义什么作为特征A的扩展,或者它的构造函数可能采用什么参数.CanCopy和隐式对象告诉Scala编译器" 就是你如何构造一个B,就是你构造一个C的方法." 隐式参数的名称是ev,代表"证据":它告诉编译器查找可以复制类型T的证据,并且证据由可以完成工作的对象提供.

根据您的应用程序,您可以通过定义另一个特征来避免一些重复的代码,该特征扩展了A,并且B和C扩展,这可以保证.copy具有特定参数的方法可用.然后你可以有一个类型的隐式对象CanCopy[ThatIntermediaryTrait],它知道调用该.copy方法.


在case类中你不需要`override val`
推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有