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

标签 scala

我正在尝试基于某些具体类型的实例创建一个新实例。我有一组类型 {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

最佳答案

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

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")

问题是 trait A 不知道如何构造后代类的实例的细节。正如 Scala 编译器所看到的,不知道你可以定义什么作为特征 A 的扩展,或者它的构造函数可能采用什么参数。 CanCopy 和隐式对象告诉 Scala 编译器“This 是你构造 B 的方式,而 this 是你构造 C 的方式。”隐式参数的名称是 ev,代表“证据”:它告诉编译器寻找类型 T 可以复制的证据,并且该证据由可以完成工作的对象提供.

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

关于scala - 在 Scala 中创建现有对象类型的新实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34081188/

相关文章:

scala - 如何为 Double 生成 Scala 范围?

scala - ;符合预期,但发现<在此放置您最喜欢的关键字>

scala - 将包含值的列作为列表转换为数组

升级测试 : object scalatest is not a member of package org

scala - 映射 Scala future

javascript - Scala.js 中的 Future

java - Akka Actors - 锁定单个资源请求

scala - 如何使用带有自定义 UDF 的 DataFrame.explode 将字符串拆分为子字符串?

Scala 交互式解释器 (REPL) - 如何将输出重定向到文本文件?

scala - 在 Spark Scala 中读取二进制文件