Scala案例类继承结构

5

我在设计我的案例类时遇到了一些困难。一个简化版本如下:

abstract class Base(s: Option[String]) {
   //code
}

case class CaseClass(s: Option[String] = None) extends Base(s) {
    //code
}

我有一个方法,想要做类似于以下的操作:

  def method(base : Base) = {
     //code
     base copy (s = Some("string"))
  }

当然我理解:

 value copy is not a member of Base

我想做的是基于我的基类(不是一个case类)创建一个新的实例。显然,这是不可能的。但你如何以一种优雅的方式解决这个问题呢?

提前感谢!


相关问题:https://dev59.com/0nE85IYBdhLWcg3wKwOE - Vasil Remeniuk
1
http://scala-programming-language.1934581.n4.nabble.com/Question-on-case-class-and-copy-method-td1936310.html - Vasil Remeniuk
2个回答

7

如果将基类参数化并在那里定义抽象的复制方法,那么子类可以从复制方法中返回自己类型的实例。在这种情况下,您希望CaseClass返回一个CaseClass,推测如此。

abstract class Base[T](s: Option[String]) {
  def copy(in: Option[String]) : T
}

case class CaseClass(s: Option[String]) extends Base[CaseClass](s) {
  def copy(in: Option[String]) = CaseClass(in)
}

case class OtherClass(s: Option[String]) extends Base[OtherClass](s) {
  def copy(in: Option[String]) = OtherClass(in)
}

def method[T <: Base[T]](base: T) : T = {
  base.copy(Some("String"))
}


scala> method(CaseClass(None))
res1: CaseClass = CaseClass(Some(String))

scala> method(OtherClass(Some("hi")))
res2: OtherClass = OtherClass(Some(String))

Base的其他子类将返回它们自己的类型。#method上的类型参数定义了Base[T]的上限。这意味着T必须是Base[T]的任何子类型,并且允许您将CaseClass和OtherClass的实例作为该方法的参数。


3
您想实现的行为是不可行的。case类的copy方法是由编译器自动生成的,一旦您在实现中添加了一个名为copy的方法,编译器将不会生成任何语法糖。
您可以使用traits重新实现copy,但它不会像生成的那样灵活(每次case类字段集更改时,您都需要更新基础trait、copymethod实现)。
sealed trait Base[T] {
   val s: Option[String]
   def copy(s: Option[String]) : T
}

case class CaseClass(override val s: Option[String] = None) extends Base[CaseClass] {
    override def copy(s: Option[String]) = CaseClass(s)
}

def method[T <: Base[T]](base : Base[T]) = base copy (s = Some("strng"))

或者,您可以按照以下方式实现method

case class CaseClass(s: Option[String] = None)

def method[X <: {def copy(s: Option[String]):X}](base : X) = 
    base copy(s = Some("string"))

scala> method(CaseClass())
res4: CaseClass = CaseClass(Some(string))

因此,如果您的case类发生变化,您将不需要Base trait,并减少修改的数量。

我喜欢第一个建议。谢谢! - tbruhn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接