首先,如果你只是想缩短你的代码,你可以做一些安全的选择。同伴对象可以被视为一个功能,所以你可以使用这样的事情:
def build2[A,B,C](m: Map[A,B], f: (B,B) => C)(k1: A, k2: A): Option[C] = for {
v1 <- m.get(k1)
v2 <- m.get(k2)
} yield f(v1, v2)
build2(m, Image)("url", "title")
这将返回一个包含结果的选项。另外,您可以使用ApplicativeBuilder
S IN Scalaz在内部做几乎相同,但有一个更好的语法:
import scalaz._, Scalaz._
(m.get("url") |@| m.get("title"))(Image)
如果你真的需要通过反射来这样做,那么最简单的方法是使用Paranamer(如电梯 - 框架确实)。 Paranamer可以通过检查字节码来恢复参数名称,所以性能会受到影响,并且由于类加载器问题(例如,REPL),它不适用于所有环境。如果你限制自己的类只有String
构造函数的参数,那么你可以做这样的:
val pn = new CachingParanamer(new BytecodeReadingParanamer)
def fill[T](m: Map[String,String])(implicit mf: ClassManifest[T]) = for {
ctor <- mf.erasure.getDeclaredConstructors.filter(m => m.getParameterTypes.forall(classOf[String]==)).headOption
parameters = pn.lookupParameterNames(ctor)
} yield ctor.newInstance(parameters.map(m): _*).asInstanceOf[T]
val img = fill[Image](m)
(注意这个例子可以选择一个默认的构造函数,因为它不会检查你会想参数计数千万)
build2的类型参数与字段数成正比。我不这么整洁,我想。 – 2014-10-09 21:02:01