使用类实例作为参数

时间:2015-04-22 21:06:53

标签: scala reflection composition functor method-call

我很确定我想做的事情可能是不可能的,反正也不是个好主意。尽管如此,这是。

我想找到一种将任何类上的任何方法转换为函数的通用方法,该函数将类的实例和方法的参数作为参数,并使用指定的参数调用实例上的方法(这是基本上方法调用如何在低级别工作:对象实例是编译器在堆栈框架上推送的隐藏参数)

示例:

鉴于

class A { def foo(param1: Type1): TypeN } 

我希望有类似的东西:

def functor[X](methodName: String): (obj: X, methodParams: Types*) => TypeN

这样:

// Type (obj: A, param1: Type1) => TypeN 
val fooFn      = functor[A]("foo")
val res: TypeN = fooFn(new A, new Type1)

这将允许类似:

def flip[A, B, C](fn: A => B => C): B => A => C = (b: B) => (a: A) => fn(a)(b)

// Type (param1: Type1) => (obj: A) => TypeN
val fooFl = flip(fooFn.curried)
List(new A, new A).map(fooFl(new Type1) _)

这样的例子可能有用:

想象一下你有:

val divide = (i: Int) => Try(2/i).toOption

List(1, 0).map(i => divide(i).getOrElse(0))

但你想要一个可以说更清洁的人:

import OptionUtils.getOrElse

List(1, 0).map(getOrElse(0) _ compose divide)

现在,我已将getOrElse手动定义为:

object OptionUtils {
    def getOrElse[A](default: A)(option: Option[A]) = option.getOrElse(default)
}

但是希望能够为指定类中的所有(或任何给定选择)方法自动定义这样的方法。理想情况下,我会有类似的东西:

val optionUtils: Utils[Option] = Utils(Option, List("getOrElse", "or"))

optionUtils.getOrElse(None, 1)   // = 1
optionUtils.getOrElseFl(1)(None) // = 1

有任何建议/意见吗?

1 个答案:

答案 0 :(得分:1)

您可以使用Java relection(此处为scala代码)

或Scala反思:

import scala.reflect._, runtime.universe._

def functor[X: TypeTag: ClassTag, R](methodName: String)(obj: X) = {   
  val m = runtimeMirror(getClass.getClassLoader)
  val method = typeTag[X].tpe.declaration(newTermName(methodName)).asMethod
  val call = m.reflect(obj).reflectMethod(method)
  (call.apply _) andThen (_.asInstanceOf[R]) 
}

scala> functor[Option[Int], Int]("get") _
res19: Option[Int] => (Seq[Any] => Int) = <function1>

scala> res19(Some(5))(Nil)
res20: Int = 5