简体   繁体   English

Scala案例类层次结构

[英]Scala case class hierarchy

I got some difficulties designing my case classes. 我在设计案例课时遇到了一些困难。 A simplified version looks like: 简化版看起来像:

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

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

And I have a method where I want to do something like: 我有一个方法,我想做的事情如下:

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

Of course I get: 我当然得到:

 value copy is not a member of Base

So what I want to do is create a new instance based on my base class (which is not a case class). 所以我想要做的是基于我的基类(不是案例类)创建一个新实例。 Obviously one can not do this. 显然,人们不能这样做。 But how would you solve this in a elegant way? 但是你如何以优雅的方式解决这个问题呢?

Thanks in advance! 提前致谢!

If you parameterize your base class and also define the abstract copy method there, you can have the subclasses return instances of their own types from the copy method. 如果参数化基类并在那里定义抽象复制方法,则可以让子类从复制方法返回自己类型的实例。 In this case, you want CaseClass to return a CaseClass, presumably. 在这种情况下,您希望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))

Other subclasses of Base would return their own types. Base的其他子类将返回自己的类型。 The type parameter on #method is defined with an upper bound of Base[T]. #method上的类型参数定义为Base [T]的上限。 This means that T must be any sub-type of Base[T] and is what allows you to supply instances of CaseClass and OtherClass as parameters to that method. 这意味着T必须是Base [T]的任何子类型,并且允许您将CaseClass和OtherClass的实例作为参数提供给该方法。

The behavior you're trying to achieve is not implementable. 您尝试实现的行为无法实现。 copy method of a case class is autogenerated by the compiler, and once you add a method called copy to your implementation, compiler will not generate any sugar. case类的copy方法由编译器自动生成,一旦你将一个名为copy的方法添加到你的实现中,编译器就不会生成任何糖。

You can reimplement copy with traits, but it will not be as flexible as the generated one (you will have to update the base trait, copy and method implementations every time the field-set of a case class changes): 您可以使用traits重新实现copy ,但它不会像生成的那样灵活(每次case类的字段集更改时,您将不得不更新基本特征, 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"))

Alternatively, you can implement method as follows: 或者,您可以按如下方式实现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))

Thus you won't need Base trait, and reduce the number of alterations, if your case classes change. 因此,如果您的案例类发生变化,您将不需要Base特征,并减少更改次数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM