Pergunta

Eu estou usando Jogar Quadro 2.1.5 em uma aplicação Java.

Eu tenho uma componente de vista que leva uma lista de objectos genéricos como um parâmetro.Neste componente, o que eu quero para iterar na lista e obter algumas propriedades de cada elemento.

Isso ficaria algo como isso:

@(elements: List[_])

@for((element, i) <- elements.view.zipWithIndex) {
    @i
    @element.id
    @element.name
}

(Eu preciso desses 3 valores)

Mas, é claro, element.id e element.name não seria compilar, mesmo se o tipo de objetos que eu coloquei na lista continha estes métodos.Então eu fiz isso:

@for((element, i) <- elements.view.zipWithIndex) {
    @defining(
        ViewsUtils.getGenericElementId(element),
        ViewsUtils.getGenericElementName(element)) {
            case (id, name, something) =>
                @i
                @id
                @name
        }
}

E em uma Java da classe de utilitário:

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();
    }
}

Isso funciona, mas eu sei que não é certo, porque ele poderia jogar uma RuntimeException em caso de um destes métodos não existe para o tipo de objeto que eu coloquei na lista.

Aqui estão os meus suppositons:

  1. Fundição de elementos

  2. Usando herança

  3. Como eu só preciso de 2 propriedades de cada objeto (id e nome), eu poderia usar um mapa, mas eu preciso que o índice de ciclo (é possível obtê-lo a partir de um mapa?) e ele não iria funcionar se eu precisava de mais do que 2 propriedades.

  4. Talvez Scala fornece a sintaxe para este tipo de coisas.

Ou talvez eu só estou olhando na direção errada.

Obrigado por sua ajuda.

Foi útil?

Solução

Ok, isso é um pouco demais para um comentário, então eu vou risco para publicá-la como uma resposta.

Supondo que você deseja nunca ter uma RuntimeException você mencionou faz sentido que o objeto de implementar alguma interface (ou mistura em uma característica, como é dito no Scala), assim você não corre o risco de ficar uma exceção e não há mais necessidade de reflexão para obter valores.

Suponha que, declarar tal traço:

trait GenericObject {
  val id: Long
  val name: String
}

Em seguida, declarar alguns casos classes:

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)

Agora você pode mudar o seu modelo como esse:

@(elements: List[GenericObject])

@for((element, i) <- elements.view.zipWithIndex) {
  @i
  @element.id
  @element.name
}

E você deve passar a lista de GenericObjects para o seu modelo:

val myObjects: List[GenericObject] = List(A(1, "A name"), B(2, "B name"), C(3, "C name"))
Ok(your_template.scala.html(myObjects))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top