Domanda

Sto usando Play Framework 2.1.5 in un'applicazione Java.

Ho un componente di visualizzazione che prende un elenco di oggetti generici come parametro. In questo componente, voglio iterare sulla lista e ottenere alcune proprietà di ciascun elemento.

Sembrerebbe qualcosa del genere:

@(elements: List[_])

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

(ho bisogno di quei valori 3)

Ma, naturalmente, element.id e element.name non si comportano anche se il tipo di oggetti che ho inserito nell'elenco conteneva questi metodi. Quindi ho fatto questo:

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

e in una classe di utilità 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();
    }
}
.

funziona, ma so che non è giusto perché potrebbe lanciare un runtimexeception nel caso in cui uno di questi metodi non esistesse per il tipo di oggetto che ho inserito nell'elenco.

Ecco i miei supposti:

    .
  1. Casting the elements

  2. usando l'ereditarience

  3. Come ho solo bisogno di 2 proprietà di ogni oggetto (ID e nome), potrei usare una mappa, ma ho bisogno dell'indice del loop (è possibile ottenerlo da una mappa?) E lo farebbe Il lavoro se avessi bisogno di più di 2 proprietà.

  4. Forse Scala fornisce la sintassi per questo tipo di roba.

  5. O forse sto solo guardando nella direzione sbagliata.

    Grazie per il tuo aiuto.

È stato utile?

Soluzione

OK, è un po 'troppo per un commento, quindi rischieremo di pubblicarlo come risposta.

Supponendo che tu desideri mai ottenere un RuntimeException che hai menzionato ha senso che il tuo oggetto implementerà qualche interfaccia (o mescolare in un tratto, come viene detto in Scala), quindi non rischierai ottenere un'eccezione e non più necessariRiflessione per ottenere valori.

Supponiamo, dichiari un tratto del genere:

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

Allora dichiari alcune classi di case:

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)
.

Ora puoi cambiare il tuo modello come questo:

@(elements: List[GenericObject])

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

E dovresti passare l'elenco dei GenericObjects al modello:

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top