It seems that type-classes appear to be the standard of applying an operation to many differing types. It's not looking up methods at runtime (well, it can, but not the pure pattern), but it could provide what you want.
trait Numeric[T] {
def times(x :T, y : T) : T
}
object Numeric {
implicit val doubleNumeric = new Numeric[Double] {
def times(x : Double, y : Double) = x*y
}
implicit val intNumeric = new Numeric[Int] {
def times(x : Int, y : Int) = x*y
}
}
def square[A : Numeric](x : A) = implicitly[Numeric[A]].times(x,x)
If you're doing this in the scala REPL, make sure the object Numeric is a true companion object to trait Numeric. You can do this by wrapping the declaration in another object, say tmp, and then importing tmp._.
Next, just call square with different values:
scala> square(2)
res6: Int = 4
scala> square(4.0)
res7: Double = 16.0
Scala actually provides a Numeric type class for use in numerical calculations, see: http://www.scala-lang.org/api/current/scala/math/Numeric.html
I also wrote an article on the type class pattern in Scala and methods of using it to adapt multiple APIs or do multiple dispatch here:
http://suereth.blogspot.com/2010/07/monkey-patching-duck-typing-and-type.html
If you google for "scala type class" you should see a lot of information.
Part #2 - An actual respond_to?
If you really really wanted a respond_to in scala, you are somewhat SOL. This is because respond_to really is a dynamic concept. You are defining a method on a class that will be called if you attempt to call a method on the class that doesn't exist. Scala doesn't abstract over method calls the way some dynamic JVM languages do. This means there are no hooks into method calls for you to intercept and interact with. The best you could do is a form of interface adaptation, or some kind of aspect-oriented post-compilation hook to rewrite bytecode for you.
There is one magic piece we can utilize, and it too is used in some AOP frameworks: The Dynamic proxy.
scala> object AllPowerfulProxy extends InvocationHandler {
| def invoke(proxy : AnyRef, m : Method, args : Array[AnyRef]) : AnyRef = {
| println(" You really want to call " + m.getName + "?")
| null // Maliciously Evil!
| }
| }
defined module AllPowerfulProxy
scala> def spawn[A : Manifest] : A = {
| val mf = implicitly[Manifest[A]]
| java.lang.reflect.Proxy.newProxyInstance(mf.erasure.getClassLoader,
| Array(mf.erasure),
| AllPowerfulProxy).asInstanceOf[A]
| }
spawn: [A](implicit evidence$1: Manifest[A])A
Now we can use it to spawn objects to any interface. Let's see what we can do:
scala> val x = spawn[TestInterface]
You really want to call toString?
java.lang.NullPointerException
at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:259)
You see what we did there? When the REPL tries to call toString on the result of an expression, it call it on our dynamic proxy. Since the proxy is a placeholder, the actual call is delegated to our AllPowerfulProxy class, how prints the message: "You really want to call toString?". The REPL then hits the null return and throws an exception. You see, using dynamic proxies moves errors to runtime, so you need to be very careful about instantiating objects and returning the correct types. Depending on the complexity of your system you should also worry about classLoaders. If you ever get a ClassCastException of Foo to Foo, then you know you're in class loader hell.
In any case, if you have other questions on dynamic proxies feel free to ask. In a statically typed languages, you're probably better off utilising type-classes and migrating to design patterns using them instead of the ones using respond_to. (You'll be surprised what you can accomplish with type classes and the type system).