Skip to content

Instantly share code, notes, and snippets.

@mccv
Created December 22, 2010 07:19
Show Gist options
  • Save mccv/751217 to your computer and use it in GitHub Desktop.
Save mccv/751217 to your computer and use it in GitHub Desktop.
Hobo Ruby send equivalent. Really just syntactic sugar for standard reflection stuff
import java.lang.reflect.Method
class Sendable(a: AnyRef) {
val methods = a.getClass.getDeclaredMethods
def wrapByte(b: Byte) = new java.lang.Byte(b)
def wrapShort(s: Short) = new java.lang.Short(s)
def wrapInt(i: Int) = new java.lang.Integer(i)
def wrapLong(l: Long) = new java.lang.Long(l)
def wrapFloat(f: Float) = new java.lang.Float(f)
def wrapDouble(d: Double) = new java.lang.Double(d)
def wrapBoolean(b: Boolean) = new java.lang.Boolean(b)
def wrapChar(c: Char) = new java.lang.Character(c)
def send(methodName: String, args: Any*) = {
val candidates = methods.filter(_.getName == methodName)
val mappedClasses = args.map(mapClass).toArray
candidates.find(method => {
val paramTypes = method.getParameterTypes
typesMatch(mappedClasses, paramTypes)
}) match {
case Some(method) => {
method.setAccessible(true)
val mappedArgs: Array[AnyRef] = args.map(wrapAny).toArray
method.invoke(a, mappedArgs:_*)
}
case _ => throw new NoSuchMethodException(methodName)
}
}
def typesMatch(args: Array[Class[_]], paramTypes: Array[Class[_]]): Boolean = {
args.length == paramTypes.length &&
args.zip(paramTypes).forall {case (arg, paramType) => paramType.isAssignableFrom(arg)}
}
def mapClass(a: Any): Class[_] = {
a match {
case b: Byte => classOf[byte]
case s: Short => classOf[short]
case i: Int => classOf[int]
case l: Long => classOf[long]
case f: Float => classOf[float]
case d: Double => classOf[double]
case b: Boolean => classOf[boolean]
case c: Char => classOf[char]
case o: AnyRef => o.getClass
case _ => classOf[Object]
}
}
def wrapAny(a: Any): AnyRef = {
a match {
case b: Byte => wrapByte(b)
case s: Short => wrapShort(s)
case i: Int => wrapInt(i)
case l: Long => wrapLong(l)
case f: Float => wrapFloat(f)
case d: Double => wrapDouble(d)
case b: Boolean => wrapBoolean(b)
case c: Char => wrapChar(c)
case o: AnyRef => o
}
}
}
object ToSendable {
implicit def toSendable(a: AnyRef) = new Sendable(a)
}
// this is how you use it
// you should just be able to paste this whole blob into the REPL
import ToSendable._
val s = "foo"
s.send("indexOf", "o")
val sb = new java.lang.StringBuilder()
sb.append("foo")
s.send("contentEquals", sb)
val al = new java.util.ArrayList[String]()
al.add("foo")
al.send("get", 1)
@jmhodges
Copy link

FYI, you are the devil.

@olix0r
Copy link

olix0r commented Sep 28, 2011

the horrrra. the horrrrrrrrrrrra!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment