2010-11-07 28 views
5

Tengo algunas dificultades para el diseño de mis clases de casos. Una versión simplificada que parece:Scala jerarquía de clases caso

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

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

Y tengo un método donde quiero hacer algo como:

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

Por supuesto me sale:

value copy is not a member of Base 

Así que lo que quieren do es crear una nueva instancia basada en mi clase base (que no es una clase de caso). Obviamente uno no puede hacer esto. ¿Pero cómo resolverías esto de una manera elegante?

¡Gracias de antemano!

+0

Pregunta relacionada: http://stackoverflow.com/questions/2911562/case-class-copy-method-abstraction –

+1

http://scala-programming-language.1934581.n4nabble.com/Question-on- -caso clases y copia-método-td1936310.html –

Respuesta

3

El comportamiento que está tratando de lograr no es implementable. copy método de una clase caso se genera automáticamente por el compilador, y una vez que se agrega un método llamado copy a su aplicación, el compilador no generará ningún azúcar.

Puede reimplementar copy con rasgos, pero no va a ser tan flexible como la generada uno (que tendrán que actualizar el rasgo de base, copy y method implementaciones cada vez que el campo establecido de unos cambios de clase caso):

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

Alternativamente, se puede implementar method de la siguiente manera:

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

Por lo tanto no necesitará Base rasgo, y reducir el número de alteraciones, si las clases de casos cambian.

+0

me gusta la primera sugerencia. ¡Gracias! – tbruhn

7

Si parametrizar su clase base y también define el método de copia Resumen de ahí, puede tener las subclases regresan casos de sus propios tipos del método de copia. En este caso, quiere que CaseClass devuelva un CaseClass, presumiblemente.

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

Otras subclases de Base devolverían sus propios tipos. El parámetro tipo en #method se define con un límite superior de Base [T]. Esto significa que T debe ser cualquier subtipo de Base [T] y es lo que le permite suministrar instancias de CaseClass y OtherClass como parámetros para ese método.

Cuestiones relacionadas