2016-07-11 11 views
5

Próbuję napisać ładną owijkę Kotlina dla szkieletu WWW przeciwko kotlin 1.0.3. W tym staram się mixin funkcji do żądania, aby go zwrócić fasoli za pośrednictwem transformacji JSON przy użyciu jackson.W kotlinach, jak zwrócić instancję zdefiniowaną przez ogólny parametr klasy

Więc w mojej bibliotece mam następujący

private val mapper: ObjectMapper = ObjectMapper().registerModule(KotlinModule()) 
fun <T : Any> Request.asDataBean(type: KClass<T>): T = mapper.readValue(this.body(), type.java) 

Ale kiedy goto użyć kodu jako takiego

post("/hello", { req, res -> 
    val bean = req.asDataBean(TestBean::class) 
}) 

It błędy mówiąc, że wartość oczekiwana fasoli ma. Chcę, aby moje API działało jak wyżej, a to, co generyczna definicja "klasy", która jest przekazywana do metodyDataBean, jest typem zwracanej wartości.

Próbowałem zostały również

fun <T> Request.asDataBean(type: KClass<*>): T = mapper.readValue(this.body(), type.java) as T 

jak również zmiany kodu wykorzystania do

val bean: TestBean = req.asDataBean(TestBean::class) 

w nadziei, co działa, ale również daje dokładnie ten sam błąd przy użyciu kodu.

Jak mogę go użyć do generycznego zdefiniowanego przez typ klasy przekazany jako parametr (bardzo podobny do tego, jak wszystkie api działa w java)?

+0

To dziwne, pierwszy fragment działa dla mnie w porządku. Czy mógłbyś podać minimalny samodzielny przykład bez zewnętrznych zależności? – voddan

+0

Nie jestem pewien, czy rozumiem. Stworzyłem repozytorium github, aby pokazać kod na https://github.com/sepatel/kotlin-seed. To cały projekt i mam nadzieję, że pomoże on lepiej opisać ten problem? Błąd, który podaje to błąd kompilacji podczas korzystania z interfejsu API: "e: Main.kt: (23, 9): Oczekiwano wartości typu Dowolny e: Main.kt: (23, 34): Wnioskowanie typu nieudane : Za mało informacji, aby odczytać parametr T w zabawie Request.asData (type: KClass <*>): T " – Ryba

Odpowiedz

4

post funkcja w przykładzie wymaga route: (Request, Response) -> Any parametr, który jest funkcją, przyjmowanie żądań i odpowiedzi oraz zwracanie wartości niepustej.

Kiedy używasz wyrażenia lambda jako route, jego typ zwracany jest wywnioskowany z ostatniego wyrażenia ciała lambda, a ponieważ w Kotlinu przypisanie nie jest wyrażeniem, następna lambda nie ma w ogóle typu zwrotu :

{ req, res -> 
    val bean = req.asDataBean(TestBean::class) 
} 

Aby to działa po prostu zrobić bean ostatniego wyrażenia

{ req, res -> 
    val bean = req.asDataBean(TestBean::class) 
    bean 
} 

lub nie używać w ogóle zadanie:

{ req, res -> req.asDataBean(TestBean::class) } 

Uwaga: Użyłem następującą definicję asDataBean funkcję:

fun <T: Any> Request.asDataBean(type: KClass<T>): T = 
    mapper.readValue(this.body(), type.java) 

Również można zrobić reified przeciążenie, która wywołuje zakaz reified jeden, dzięki czemu nie trzeba odsłaniamy wszystkie urządzenia wewnętrzne:

inline fun <reified T: Any> Request.asDataBean(): T = 
    asDataBean(T::class) 

req.asDataBean<TestBean>() // usage 
+0

Dzięki, nie mogę uwierzyć, że źle zinterpretowałem komunikat o błędzie, po przeczytaniu twojego powodu poczułem się jak początkujący. Dzięki za napiwek reifikowany, nigdy nie myślałem o tym i to brzmi jak najlepszy rozwiązanie danego problemu. – Ryba

5

Bardziej Kotlin idiomatyczne sposób byłoby użyć reified type parameters:

inline fun <reified T : Any> Request.asDataBean(): T = mapper.readValue(this.body(), T::class.java) 

które następnie mogą być spożywane jako:

post("/hello", { req, res -> 
    val bean = req.bodyAs<TestBean>() 
    res.body("Ok") 
}) 
+1

Aby wstawić musisz mieć wszystkie zmienne publicznie dostępne iw tym przypadku program odwzorowujący jest zdefiniowany prywatnie w bibliotece, a więc inline nie działa. Poza tym próbowałem już zrobić to w sposób, o którym wspomniałeś, czyniąc jawnicę publiczną i czyniąc ją reifikowaną, i nadal nie była ona użyteczna, jak opisałeś, dając błąd kompilatora dowolnego typu. – Ryba

+0

Utworzono oddział https://github.com/sepatel/kotlin-seed/tree/reified w celu wykazania, że ​​nawet jako reifikat nie działa, podając błąd "Oczekiwana wartość typu Any", gdy jest używany. – Ryba

+0

@Ryba parametry 'post ("/hello ", {res, req-> ...' lamba musi zwracać 'Any' .Zadanie w Kotlin nie jest wyrażeniem, dlatego nie ma wartości. zwracana wartość: – miensol

Powiązane problemy