Question

J'utilise Play Framework 2.1.5 dans une application Java.

J'ai un composant de vue qui prend une liste d'objets génériques comme paramètre.Dans ce composant, je souhaite parcourir la liste et obtenir quelques propriétés de chaque élément.

Cela ressemblerait à quelque chose comme ceci :

@(elements: List[_])

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

(J'ai besoin de ces 3 valeurs)

Mais bien sûr, element.id et element.name ne compilerait pas même si le type d'objets que j'ai mis dans la liste contenait ces méthodes.J'ai donc fait ceci :

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

Et dans une classe utilitaire 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();
    }
}

Cela fonctionne mais je sais que ce n'est pas correct car cela pourrait lancer une RuntimeException au cas où l'une de ces méthodes n'existerait pas pour le type d'objet que j'ai mis dans la liste.

Voici mes hypothèses :

  1. Couler les éléments

  2. Utiliser l'héritage

  3. Comme j'ai juste besoin de 2 propriétés de chaque objet (id et nom), je pourrais utiliser une carte, mais j'ai besoin de l'index de la boucle (est-il possible de l'obtenir à partir d'une carte ?) et cela ne fonctionnerait pas si j'en avais besoin. plus de 2 propriétés.

  4. Peut-être que Scala fournit la syntaxe pour ce genre de choses.

Ou peut-être que je regarde simplement dans la mauvaise direction.

Merci pour votre aide.

Était-ce utile?

La solution

Ok, c'est un peu trop pour un commentaire, donc je vais risquer de le poster comme réponse.

En supposant que vous souhaitiez ne jamais obtenir de RuntimeException vous avez mentionné qu'il est logique que votre objet implémente une interface (ou mélange un trait, comme il est dit dans Scala), vous ne risquerez donc pas d'obtenir une exception et vous n'aurez plus besoin de réflexion pour obtenir des valeurs.

Supposons que vous déclariez un tel trait :

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

Ensuite, vous déclarez quelques classes de cas :

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)

Vous pouvez maintenant modifier votre modèle comme ceci :

@(elements: List[GenericObject])

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

Et tu devrais passer la liste des GenericObjects à votre modèle :

val myObjects: List[GenericObject] = List(A(1, "A name"), B(2, "B name"), C(3, "C name"))
Ok(your_template.scala.html(myObjects))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top