2010-11-07 54 views
5

设计我的案例类时遇到了一些困难。一个简化的版本是这样的:Scala案例类层次结构

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 

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

提前致谢!

+0

相关问题:http://stackoverflow.com/questions/2911562/case-class-copy-method-abstraction – 2010-11-07 19:49:49

+1

http://scala-programming-language.1934581.n4.nabble.com/Question-on- case-class-and-copy-method-td1936310.html – 2010-11-07 20:13:39

回答

3

您尝试实现的行为不可实施。 copy case类的方法是由编译器自动生成的,一旦向实现中添加了一个名为copy的方法,编译器将不会生成任何糖。

您可以重新实现copy与特质,但它不会如此灵活生成的一个(你将有更新的基础特质,copy和每场设定的情况下,类发生变化时method实现):

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

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

+0

我喜欢第一个建议。谢谢! – tbruhn 2010-11-08 20:02:21

7

如果参数化您的基类并在其中定义抽象副本方法,则可以让子类从copy方法返回它们自己类型的实例。在这种情况下,你想让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的实例作为该方法的参数。