Created
December 22, 2010 07:19
-
-
Save mccv/751217 to your computer and use it in GitHub Desktop.
Hobo Ruby send equivalent. Really just syntactic sugar for standard reflection stuff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI, you are the devil.