2010-11-07 108 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的實例作爲該方法的參數。