【问题标题】:Scala case class hierarchyScala案例类层次结构
【发布时间】:2011-05-06 09:05:46
【问题描述】:

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

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

所以我想做的是基于我的基类(不是案例类)创建一个新实例。显然不能做到这一点。但是你会如何优雅地解决这个问题呢?

提前致谢!

【问题讨论】:

标签: class inheritance scala hierarchy case


【解决方案1】:

如果您参数化您的基类并在那里定义抽象复制方法,您可以让子类从复制方法返回它们自己类型的实例。在这种情况下,您可能希望 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 的实例作为该方法的参数。

【讨论】:

    【解决方案2】:

    您试图实现的行为是不可实现的。案例类的copy 方法是由编译器自动生成的,一旦你在实现中添加了一个名为copy 的方法,编译器就不会生成任何糖。

    您可以使用特征重新实现copy,但它不会像生成的那样灵活(您必须在每次案例的字段集时更新基本特征,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))
    

    因此,如果您的案例类别发生变化,您将不需要 Base 特征,并减少更改次数。

    【讨论】:

    • 我喜欢第一个建议。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    • 2011-11-08
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多