2013-03-07 10 views
6

chcę obiekt do wdrożenia cechę Iterable i zdać dodatkowy parametr niejawny do wdrożonego sposobu realizacji:metod cech z dodatkowych parametrów ukrytych

object MyRepository extends Iterable[Something] { 

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

} 

Oczywiście to nie działa, ponieważ nie ma sposobu iterator niejawny parametr i dlatego nie jest implementowany przez metodę pokazaną powyżej.

przypadek przykład stosowanie jest metoda map który chcę zastosować do wartości repozytorium:

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

Czy istnieje jakiś sposób, aby wdrożyć cechę Iterable i uchwycić niejawny pramameter?

+0

Próbowałem bardzo ciężko, ale nie mogłem zrozumieć, co mówisz. Chcesz zmienić swoje pytanie? –

+0

@ RégisJean-Gilles: Dodałem przykład i mam nadzieję, że to pokazuje moją intencję. – deamon

+0

Och, oczywiście, widzę. Chcesz zaimplementować 'Iterable.iterator', ale potrzebujesz dodatkowego niejawnego parametru (w implementacji), który oczywiście nie jest zdefiniowany w oryginalnym podpisie. –

Odpowiedz

9

Biorąc pod uwagę, że Iterable.iterator nie ma tego niejawnego w podpisie, nie można oczekiwać, że będzie w stanie zaimplementować tę metodę, dodając ją niejawnie: to byłaby inna metoda (konkretnie inne przeciążenie).

Jednak jeśli MyRepository była klasą, a nie obiektem, można uchwycić niejawne w konstruktorze klasy. A jeśli chcesz zachować ten sam styl użycia (jak w przypadku MyRepository.map{ ... }, a nie new MyRepository.map{ ... }), możesz podać niejawną konwersję z obiektu na klasę.

Oto przykład:

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 
} 

Co się dzieje teraz, kiedy robisz MyRepository.map(...) jest, że obiekt zostanie niejawnie konwertowane do instancji MyRepositoryIterable który przechwytuje niejawny wartość EntityManager. MyRepositoryIterable to klasa, która faktycznie implementuje Iterable.

+0

Czy to nie oznacza, że ​​muszę utworzyć nowe repozytorium dla każdej transakcji? – deamon

+1

Nie. 'MyRepository' jest nadal obiektem (a przez to unikalnym). Twój przykładowy kod (metoda 'get') działałby tak, jak jest, bez żadnych zmian, tylko teraz wywołanie' map' implikuje nieuchronnie utworzenie instancji 'MyRepositoryIterable' (ale jest to przezroczyste). –