Frage

Ich verwende Play Framework 2.1.5 in einer Java-Anwendung.

Ich habe eine Ansichtskomponente, die eine Liste generischer Objekte als Parameter akzeptiert.In dieser Komponente möchte ich die Liste durchlaufen und einige Eigenschaften jedes Elements abrufen.

Das würde etwa so aussehen:

@(elements: List[_])

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

(Ich brauche diese 3 Werte)

Aber natürlich, element.id Und element.name würde nicht kompiliert werden, selbst wenn die Art der Objekte, die ich in die Liste eingefügt habe, diese Methoden enthalten würde.Also habe ich Folgendes gemacht:

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

Und in einer Java-Dienstprogrammklasse:

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

Das funktioniert, aber ich weiß, dass es nicht richtig ist, weil es eine RuntimeException auslösen könnte, falls eine dieser Methoden für den Objekttyp, den ich in die Liste aufgenommen habe, nicht existiert.

Hier sind meine Vermutungen:

  1. Die Elemente gießen

  2. Vererbung nutzen

  3. Da ich nur zwei Eigenschaften jedes Objekts (ID und Name) benötige, könnte ich eine Karte verwenden, aber ich brauche den Index der Schleife (ist es möglich, ihn von einer Karte abzurufen?) und es würde nicht funktionieren, wenn ich es bräuchte mehr als 2 Eigenschaften.

  4. Vielleicht stellt Scala die Syntax für solche Dinge bereit.

Oder vielleicht schaue ich einfach in die falsche Richtung.

Ich danke Ihnen für Ihre Hilfe.

War es hilfreich?

Lösung

Ok, das ist etwas zu viel für einen Kommentar, also riskiere ich, ihn als Antwort zu posten.

Vorausgesetzt, Sie möchten niemals eine bekommen RuntimeException Sie haben erwähnt, dass es sinnvoll ist, dass Ihr Objekt eine Schnittstelle implementiert (oder ein Merkmal einmischt, wie es in Scala heißt), sodass Sie nicht riskieren, eine Ausnahme zu erhalten, und keine Reflexion mehr benötigen, um Werte zu erhalten.

Angenommen, Sie deklarieren ein solches Merkmal:

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

Dann deklarieren Sie einige Fallklassen:

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)

Jetzt können Sie Ihre Vorlage wie folgt ändern:

@(elements: List[GenericObject])

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

Und Sie sollten die Liste von weitergeben GenericObjects zu Ihrer Vorlage:

val myObjects: List[GenericObject] = List(A(1, "A name"), B(2, "B name"), C(3, "C name"))
Ok(your_template.scala.html(myObjects))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top