2010-10-13 21 views
7

Vorrei scrivere un alias di tipo per abbreviare, codice Scala bello e incapsulato. Supponiamo di avere qualche collezione che abbia la proprietà di essere una lista di mappe, il cui valore è tuple. Il mio tipo scriverebbe qualcosa come List[Map[Int, (String, String)]], o qualcosa di più generico come la mia applicazione lo consente. Potrei immaginare di avere un supertipo che chiede un Seq[MapLike[Int, Any]] o qualsiasi cosa galleggi la mia barca, con sottoclassi concrete che sono più specifiche.Alias ​​di tipo Scala incluso oggetto companion [principiante]

Vorrei quindi scrivere un alias per questo tipo lungo.

class ConcreteClass { 
    type DataType = List[Map[Int, (String, String)]] 
    ... 
} 

Vorrei poi felicemente utilizzare ConcreteClass#DataType ovunque posso prendere uno, e usarlo.

Ora supponiamo che io aggiungo una funzione

def foo(a : DataType) { ... } 

E voglio chiamarlo da fuori con una lista vuota. Posso chiamare foo(List()), ma quando voglio cambiare il mio tipo sottostante per essere un altro tipo di Seq, dovrò tornare e modificare anche questo codice. Inoltre, non è molto esplicito questa lista vuota è intesa come DataType. E l'oggetto companion non ha i metodi associati List, quindi non posso chiamare DataType() o DataType.empty. Sarà ancora più fastidioso quando avrò bisogno di liste non vuote poiché dovrò scrivere una parte significativa di questo lungo tipo.

C'è un modo in cui posso chiedere a Scala di capire il mio tipo come la stessa cosa, incluso l'oggetto companion con i suoi metodi di creazione, nell'interesse di accorciare il codice e metterlo in blackbox? Oppure, qualsiasi motivo per cui non dovrei fare questo in primo luogo?

risposta

7

la risposta era in realtà molto semplice:

class ConcreteClass { 
    type DataType = List[String] 
} 
object ConcreteClass { 
    val DataType = List 
} 
val d = ConcreteClass.DataType.empty 

questo modo il mio codice per chiamare ConcreteClass.DataType di costruire liste con tutti i metodi di List e poco sforzo.

Grazie mille a Oleg per l'approfondimento. La sua risposta è anche la migliore nel caso in cui non si desideri delegare ad elencare alcuna chiamata a ConcreteClass.DataType, ma controllare con precisione cosa si desidera consentire ai chiamanti di fare.

+2

Se non intendi sottoclassi di 'ConcreteClass' per sovrascrivere' DataType', potresti essere meglio mettere entrambi gli alias 'type' e' val' nell'oggetto companion (invece di averne uno nella classe). Ecco come funzionano gli alias nell'oggetto del pacchetto 'scala'. –

+0

Hai davvero ragione. Lo farò d'ora in poi. Grazie. – Jean

+1

Tranne d è il tipo Lista [Nothing] – sourcedelica

5

Che dire di questo?

 
class ConcreteClass { 
    type DataType = List[String] 
} 
object DataType { 
    def apply(): ConcreteClass#DataType = Nil 
} 
//... 
val a = DataType() 

+0

Questo funziona. Grazie. Comunque con questo devo definire ogni singolo metodo di List per fare quello che voglio, ed è un po 'prolisso. È molto buono avere il controllo su ciò che può essere chiamato anche. Grazie alla tua risposta penso di aver ottenuto la soluzione generica per "chiamare tutti i metodi di lista": pubblicandola ora. Grazie mille :) – Jean