Play 框架 2 - Scala 模板:如何调用通用对象的特定方法?
题
我在 Java 应用程序中使用 Play Framework 2.1.5。
我有一个视图组件,它将通用对象列表作为参数。在此组件中,我想迭代列表并获取每个元素的一些属性。
这看起来像这样:
@(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。
这是我的假设:
铸造元素
使用继承
由于我只需要每个对象的 2 个属性(id 和 name),我可以使用地图,但我需要循环的索引(是否可以从地图中获取它?),如果我需要它就不起作用超过 2 个属性。
也许 Scala 提供了此类内容的语法。
或者也许我只是看错了方向。
感谢您的帮助。
解决方案
好吧,这对于评论来说有点太多了,所以我会冒险将其发布为答案。
假设你希望永远得不到 RuntimeException
您提到您的对象实现某些接口(或混合特征,如 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
}
你应该传递以下列表 GenericObject
到你的模板:
val myObjects: List[GenericObject] = List(A(1, "A name"), B(2, "B name"), C(3, "C name"))
Ok(your_template.scala.html(myObjects))
不隶属于 StackOverflow