Определение и ссылка на общий тип, связанный в подписи шаблона воспроизведения

#java #scala #templates #generics #playframework-2.2

#java #scala #шаблоны #общие #playframework-2.2

Вопрос:

У меня есть несколько отсортированных карт, с указанием времени и значением некоторого типа. Для иллюстрации рассмотрим, что у меня есть 3 карты (на Java):

 SortedMap<OffsetDateTime, Foo> foo;
SortedMap<OffsetDateTime, Boo> bar;
SortedMap<OffsetDateTime, Baz> baz;
 

Я хочу написать общий шаблон воспроизведения, который принимает карту и функцию визуализации и выводит каждую пару.

В шаблоне я могу определить локальную функцию со следующей сигнатурой:

 @renderTrace[T <: Any](trace: ImmutableSortedMap[OffsetDateTime, Option[T]], renderer: (T) => Html) = {
 

Однако я хотел бы использовать эту функцию в нескольких шаблонах, поэтому я не хочу определять ее локально. Скорее, я надеялся определить его как собственный шаблон (in RenderTrace.scala.html ).

К сожалению, я, похоже, не могу указать конструкцию типа [T <: Any] в подписи шаблона.

Как я могу определить повторно используемую типизированную функцию?

Комментарии:

1. определите его во внешнем модуле и выполните @import <yourmodule> в шаблоне?

2. Извините @Ashalynd, я не следую вашему предложению. Чтобы прояснить мою цель: поскольку сигнатура шаблона не является обычной сигнатурой метода Scala (в отличие от локальных функций, которые в значительной степени являются), я не нашел способ включить [T <: Any] .

3. Здесь я столкнулся с той же проблемой — пытался написать несколько общих шаблонов, используя scala только для «помощников» и в самих шаблонах. Итак, какое решение вы выбрали в итоге?

4. @sandman: я использовал ответ ниже.

Ответ №1:

Чтобы конкретизировать предложение @Ashalynd, компилятор шаблонов, похоже, недостаточно умен для обработки параметров типа. Иногда вы можете использовать символ подчеркивания в качестве параметра типа (только если вам все равно, какой тип), но это не один из тех случаев.

Шаблон воспроизведения (теперь называемый twirl) — это, по сути, просто функция, которая выдает результат типа play.twirl.api.Html (или play.api.templates.Html для Play 2.2). Необходимо обойти компилятор шаблонов, поэтому определите вспомогательный пакет, содержащий вашу функцию:

 package viewhelpers

import play.twirl.api.Html // play.api.templates.Html for 2.2

object ViewExtension {

    def renderTrace[T <: Any](trace: ImmutableSortedMap[OffsetDateTime, Option[T]], renderer: (T) => Html): Html = ...

}
 

Реализация renderTrace может выглядеть не так красиво, как в шаблоне представления, но, по крайней мере, она может работать сейчас.

Затем в представлении:

 @(someParams: ....)
@import viewhelpers.ViewExtension

@{ViewExtension.renderTrace(...)}
 

Комментарии:

1. Правильно. Это то, чего я боялся. К сожалению, для меня мои контроллеры находятся на Java, поэтому мой помощник может быть еще более неприглядным. Или я могу также писать объекты Scala даже в приложении Play на основе Java? (Я проведу расследование, но знаете ли вы?)

2. Вы можете смешивать объекты Scala, поскольку обе версии Scala / Java в любом случае компилируются sbt через play / activator.