2

In Java, I can do TheClass.class.getName() to get to a class name that I need as a String somewhere (avoiding to type it again, avoiding typos, clearly documenting dependencies).

Can I do the same for a function (or other things) in Scala ?

val theName : String = nameOf[aFunctionThatICanSeeHere]
1
  • Actually inside the brackets scala awaits type parameter, how do you expect to identify function by its type? Commented Dec 3, 2015 at 7:58

3 Answers 3

3

For a class name:

val theName = classOf[TheClass].getName

classOf[TheClass] is the same as TheClass.class in Java.

For names of methods etc. you could use reflection, just like in Java. (Note that the Scala reflection API is currently still experimental).

edit - Scala is, besides an object-oriented programming language, also a functional programming language. You can pass functions as values. For example:

class Thing {
  def method(x: Int): Int = x + 2
}

val thing = new Thing

// fn is a value that refers to a method
// similar to (but not really the same as) a method reference in Java
val fn = thing.method _

// you can call the method through fn
val result = fn(3) // same as thing.method(3)
Sign up to request clarification or add additional context in comments.

6 Comments

I think, experimental tag means that current reflection lib is heavily based on compiler internals and is a subject to change with possible change of compiler implementation.
Do you have an example for using reflection to get a method name?
See Inspecting a Runtime Type which shows how to, among other things, inspect a type and find the methods on it.
Can't seem to find anything in there that would let me get to a method name from a reference to it (like classOf[TheClass] does it). All examples have the name of the method specified as a String. I want the opposite: Get to that String (the method name), from some kind of literal/symbol in source code.
I guess the question is "Is there a Scala equivalent to a Java 8 method reference like ClassName::methodName ?")
|
2

You can use scala-nameof to get a function name, variable name, class member name, or type name. It happens at compile-time so there's no reflection involved and no runtime dependency needed.

val theName = nameOf(aFunctionThatICanSeeHere _)

will compile to:

val theName = "aFunctionThatICanSeeHere"

Comments

1

This uses the ObjectWeb ASM library. This extracts all the methods of a given class instance. There is also code for getting method name inside this.

import org.objectweb.asm.Type
import org.objectweb.asm.Type
import org.objectweb.asm.tree._
import org.objectweb.asm.util._
import java.lang.reflect.Method


case class ScalaMethod(name:String, returnType:Type, params:List[Param], parentClassName:String)
case class Param(paraName:String, paraType:Type)
object MethodReader {
  /*
   * stackoverflow.com/questions/7640617/how-to-get-parameter-names-and-types-via-reflection-in-scala-java-methods
   */
  def getMethods(c:AnyRef, is:java.io.InputStream) = {
    val cn = new ClassNode();
    val cr = new ClassReader(is);
    cr.accept(cn, 0);
    is.close();
    val methods = cn.methods.asInstanceOf[java.util.List[MethodNode]];
    var mList:List[ScalaMethod] = Nil
    if (methods.size > 0) for (i <- 1 to methods.size) {
      try {
        val m:MethodNode = methods.get(i-1)
        val argTypes:Array[Type] = Type.getArgumentTypes(m.desc);
        val vars = m.localVariables.asInstanceOf[java.util.List[LocalVariableNode]];
        var pList:List[Param] = Nil
        if (argTypes.length > 0 && vars.length > 0) for (i <- 1 to argTypes.length) {
          // The first local variable actually represents the "this" object in some cases
          val difference = if (vars.get(0).name == "this") 0 else 1
          pList = Param(vars.get(i-difference).name, argTypes(i-1)) :: pList
        }
        mList = ScalaMethod(m.name, Type.getReturnType(m.desc), pList.reverse, c.getClass.getCanonicalName):: mList
      } catch { 
        case e:Throwable => 
      }
    }
    mList.reverse
  }
  def getMethods(c, is):List[ScalaMethod] = {
    val t = Type.getType(c);
    val url = t.getInternalName() + ".class";
    val is = try {
      val cl = c.getClassLoader();
      val is = cl.getResourceAsStream(url);
      if (is == null) throw new IllegalArgumentException("Cannot find class: " + url);
      else is
    } catch {
      case e:IllegalArgumentException => 
        new java.io.FileInputStream(url)
    }
  }
}

2 Comments

Hmm. So how do I use this to find the name of the given method?
The line mList = ScalaMethod(m.name, Type.getReturnType(m.desc), pList.reverse, c.getClass.getCanonicalName):: mList gets the method name. The code also gives additional information (such as method parameters) in case you need it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.