2011-08-26 16 views
17

Attualmente sto imparando Scala e ho qualche problema nella progettazione delle mie case classes. Ho bisogno di due case case che abbiano le stesse proprietà. Quindi ho pensato che sarebbe stata una buona idea ereditare da una classe base astratta che definisce queste proprietà. Tuttavia questo codice non viene compilatoClassi case ereditate dalla classe astratta

abstract class Resource(val uri : String) 

case class File(uri : String) extends Resource(uri) 
case class Folder(uri : String) extends Resource(uri) 

perché uri nei costruttori caso classe sarebbe sovrascrivere la proprietà uri della classe base.

Quale sarebbe il modo corretto di progettare questo?

Voglio essere in grado di fare qualcosa di simile

val arr = Array[Resource](File("test"), Folder("test2")) 

arr.foreach { r : Resource => r match { 
    case f : File => println("It's a file") 
    case f : Folder => println("It's a folder") 
} } 

Il codice Java "equivalente" dovrebbe essere qualcosa come

abstract class Resource { 
    private String uri; 

    public Resource(String uri) { 
     this.uri = uri 
    } 

    public String getUri() { 
     return uri; 
    } 
} 

// same for Folder 
class File extends Resource { 
    public File(String uri) { 
     super(uri); 
    } 
} 

risposta

25

La sintassi corretta dovrebbe essere:

abstract class Resource { 
    val uri: String 
} 

case class File(uri : String) extends Resource 
case class Folder(uri : String) extends Resource 


Stream[Resource](File("test"), Folder("test2")) foreach { 
    r : Resource => r match { 
    case f : File => println("It's a file") 
    case f : Folder => println("It's a folder") 
} } 

EDIT

Senza classi case:

abstract class Resource(val uri : String) 

class File(uri : String) extends Resource(uri) { 
    override def toString = "..." 
} 
object File { 
    def apply(uri: String) = new File(uri) 
} 

class Folder(uri : String) extends Resource(uri) { 
    override def toString = "..." 
} 
object Folder { 
    def apply(uri: String) = new Folder(uri) 
} 
+1

Tuttavia, questo duplica la proprietà 'uri' e il getter sia in' File' che in 'Cartella'. C'è qualche possibilità di ottenere codice pulito che assomigli all'esempio Java nella mia domanda? –

+0

Allora perché usi le classi dei casi? Le classi di casi aggiungono getter e setter. Scrivi classi normali e i loro oggetti complementari. – onof

+0

Perché questo sarebbe troppo codice piastra della caldaia? ;-) Puoi per favore fornire un esempio? –

5

a rendere questi due classe caso estende un tratto comune che lo definiscono interfaccia e dovrebbe funzionare.

BTW, è necessario un identificativo prima della clausola di tipo nell'istruzione case.

trait Resource { 
    val uri: String 
} 

case class File(uri : String) extends Resource 
case class Folder(uri : String) extends Resource 

val arr = Array[Resource](File("test"), Folder("test2")) 

arr.foreach { r : Resource => r match { 
    case s: File => println("It's a file") 
    case s: Folder => println("It's a folder") 
}} 
+1

Questo funziona tuttavia i metodi di proprietà e getter uri sono immagazzinato sia 'File' che' Folder' (duplicato). Speravo di avere un codice pulito come l'esempio Java sopra (ho aggiornato la mia domanda). –