Play Framework 2 - Scala Шаблон: Как вызвать определенный метод на общий объект?

StackOverflow https://stackoverflow.com//questions/22039081

Вопрос

Я использую 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 в случае, если один из этих методов не существует для типа объекта, который я поставил в список.

Вот мои интермомотоны:

  1. отливка элементов

  2. Использование наследства

  3. Как мне просто нужно 2 свойства каждого объекта (ID и имя), я мог бы использовать карту, но мне нужен индекс петли (возможно ли получить его с карты?) И это бы Работа, если мне нужна более 2 свойств.

  4. Может быть, Scala предоставляет синтаксис для такого рода вещей.

  5. или, возможно, я просто смотрю в неправильном направлении.

    Спасибо за вашу помощь.

Это было полезно?

Решение

Хорошо, это слишком много для комментариев, поэтому я рискую публиковать его как ответ.

Предполагая, что вы хотите никогда не получить генеракодицетагкод, который вы упомянули, имеет смысл, что ваш объект реализует какой-то интерфейс (или смешать в черте, как говорится в 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
}
.

, и вы должны пройти список RuntimeExceptions к вашему шаблону:

val myObjects: List[GenericObject] = List(A(1, "A name"), B(2, "B name"), C(3, "C name"))
Ok(your_template.scala.html(myObjects))
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top