2013-03-07 15 views
6

voglio un oggetto per attuare il tratto Iterable e passare un parametro implicito aggiuntivo al metodo implementato applicazione:metodi di tratti con ulteriori parametri impliciti

object MyRepository extends Iterable[Something] { 

    def iterator(implict entityManager: EntityManager): Iterator[Something] = ... 

} 

Ovviamente questo non funziona perché il metodo non ha iterator parametro implicito e quindi non è implementato con il metodo mostrato sopra.

Un caso ad esempio l'uso è il metodo map che voglio applicare ai valori del repository:

def get = Action { 
    Transaction { implicit EntityManager => 
     val result = MyRepository.map(s => s ...) 
    } 
    } 

C'è qualche modo per attuare il Iterable tratto e catturare il pramameter implicita?

+0

Ho provato molto, ma non riuscivo a dare un senso a quello che stai dicendo. Cura di riformulare la tua domanda? –

+0

@ RégisJean-Gilles: ho aggiunto un esempio e spero che mostri la mia intenzione. – deamon

+0

Oh, certo, capisco. Si desidera implementare 'Iterable.iterator' ma è necessario un parametro implicito aggiuntivo (nell'implementazione) che non è ovviamente definito nella firma originale. –

risposta

9

Dato che Iterable.iterator non ha questo implicito nella sua firma, non ci si può aspettare di essere in grado di implementare questo metodo aggiungendo questo implicito: sarebbe un altro metodo (in particolare, un altro sovraccarico).

Tuttavia, se MyRepository era una classe anziché un oggetto, è possibile acquisire l'implicito nel costruttore della classe. E se si desidera mantenere lo stesso stile di utilizzo (come in MyRepository.map{ ... } anziché new MyRepository.map{ ... }), ciò che si può fare è fornire una conversione implicita dall'oggetto alla classe.

Ecco un esempio:

object MyRepository { 
    class MyRepositoryIterable(implicit entityManager: EntityManager) extends Iterable[Something] { 
    def iterator: Iterator[Something] = ??? 
    } 
    implicit def toIterable(rep: MyRepository.type)(implicit entityManager: EntityManager): MyRepositoryIterable = new MyRepositoryIterable 
} 

Cosa succede ora quando fai MyRepository.map(...) è che l'oggetto viene implicitamente convertito in un'istanza di MyRepositoryIterable che cattura il valore implicito EntityManager. Il MyRepositoryIterable è la classe che implementa effettivamente Iterable.

+0

Non implicherebbe che ho bisogno di creare un nuovo repository per ogni transazione? – deamon

+1

No. 'MyRepository' è ancora un oggetto (e quindi univoco). Il tuo codice di esempio (il metodo 'get') funzionerebbe come è, senza alcuna modifica, solo ora la chiamata a' map' implica implacabilmente la creazione di un'istanza 'MyRepositoryIterable' (ma questo è trasparente). –

Problemi correlati