Play Framework 2 - Scala Шаблон: Как вызвать определенный метод на общий объект?
Вопрос
Я использую Play Framework 2.1.5 в приложении Java.
У меня есть компонент просмотра, который принимает список общих объектов в качестве параметра. В этом компоненте я хочу повторять свой список и получить некоторые свойства каждого элемента.
Это будет выглядеть как что-то вроде этого:
@(elements: List[_])
@for((element, i) <- elements.view.zipWithIndex) {
@i
@element.id
@element.name
}
.
(Мне нужны эти 3 значения)
Но, конечно, element.id
и element.name
не скомпилируются, даже если тип объектов, которые я положил в список, содержал эти методы. Так что я сделал это:
@for((element, i) <- elements.view.zipWithIndex) {
@defining(
ViewsUtils.getGenericElementId(element),
ViewsUtils.getGenericElementName(element)) {
case (id, name, something) =>
@i
@id
@name
}
}
.
и в классе утилиты Java:
public final class ViewsUtils {
public static String getGenericElementId(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
return object.getClass().getMethod("getId").invoke(object).toString();
}
public static String getGenericElementName(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
return object.getClass().getMethod("getName").invoke(object).toString();
}
}
.
Это работает, но я знаю, что это не правильно, потому что он может бросить runtimeexception в случае, если один из этих методов не существует для типа объекта, который я поставил в список.
Вот мои интермомотоны:
-
отливка элементов
-
Использование наследства
-
Как мне просто нужно 2 свойства каждого объекта (ID и имя), я мог бы использовать карту, но мне нужен индекс петли (возможно ли получить его с карты?) И это бы Работа, если мне нужна более 2 свойств.
-
Может быть, Scala предоставляет синтаксис для такого рода вещей.
или, возможно, я просто смотрю в неправильном направлении.
Спасибо за вашу помощь.
Решение
Хорошо, это слишком много для комментариев, поэтому я рискую публиковать его как ответ.
Предполагая, что вы хотите никогда не получить генеракодицетагкод, который вы упомянули, имеет смысл, что ваш объект реализует какой-то интерфейс (или смешать в черте, как говорится в Scala), поэтому вы не будете рисковать получить исключение и больше не нужноОтражение для получения значений.
Предположим, вы объявляете такую черту:
trait GenericObject {
val id: Long
val name: String
}
.
Тогда вы объявляете несколько классов:
case class A(id: Long, name: String, someOtherField: SomeType) extends GenericObject {
//your implementation
}
case class B(id: Long, name: String) extends GenericObject
case class C(id: Long, name: String) extends B(id, name)
.
Теперь вы можете изменить свой шаблон так:
@(elements: List[GenericObject])
@for((element, i) <- elements.view.zipWithIndex) {
@i
@element.id
@element.name
}
.
, и вы должны пройти список RuntimeException
s к вашему шаблону:
val myObjects: List[GenericObject] = List(A(1, "A name"), B(2, "B name"), C(3, "C name"))
Ok(your_template.scala.html(myObjects))
.