2016-10-23 3 views
0

Я хочу получить список методов в вложенном объекте-компаньоне с использованием отражения Java. Это A.B в приведенном ниже примере.Получить статические методы класса, вложенного в объект, используя отражение Java

object A { 
    object B { 
    def foo: Int = 4 
    } 

    class B {} 

    def bar: Int = 5 
} 

class A {} 

// This works, `bar` is printed. 
println(classOf[A].getMethods.map(_.getName).mkString("\n")) 

// This doesn't work, `foo` is not printed. 
println(classOf[A.B].getMethods.map(_.getName).mkString("\n")) 

Кажется, как получить список методов на внешнем компаньона объект A работает, но не на вложенной один.

Есть ли способ написать метод, который будет принимать Class[_] и получить все методы, определенные на сопутствующем объекте, является ли он вложенным или нет?

+0

Вы уверены, что вы вставили правильный код? Кажется, я не могу воспроизвести первый отпечаток, как вы заявили. – pedrofurla

+0

И classOf [A] не может иметь метод 'bar', иначе' new A' также будет иметь панель методов. – pedrofurla

+0

Проверьте эту сессию репликации https://gist.github.com/pedrofurla/d48d1f1fc759e2849400cb91fc69695b out – pedrofurla

ответ

1

classOf[A] и classOf[A.B] не являются классами сопутствующих объектов, поэтому у них нет этих методов. A.type и B.type sortof, но они не являются типами классов в Scala. Как pedrofurla указывает, что вы можете сделать это, чтобы достичь их в качестве объектов класса Java:

scala> A.getClass.getDeclaredMethods 
res17: Array[java.lang.reflect.Method] = Array(public int A$.bar()) 

scala> A.B.getClass.getDeclaredMethods 
res18: Array[java.lang.reflect.Method] = Array(public int A$B$.foo()) 
+0

Обратите внимание, что 'A' и' AB' как объекты, а не классы. – pedrofurla

+0

Существует несогласованность с тем, как scalac создает классы для объектов-компаньонов. classOf [A] на самом деле имел бы bar(), определенный на нем как * статический * метод (см. http://scastie.org/23296). По какой-то причине foo() не будет отображаться как static в A.B.getClass. – thesamet

1

я придумал следующий код, который делает предположение, что имя класса компаньона может быть определена путем добавления $ к классу имя.

Это позволяет вызов метода спутника данного класса соответствующего типа, независимо от того, вложен ли спутник или нет:

def getCompanion(clazz: Class[_]) = { 
    Class.forName(clazz.getName + "$").getField("MODULE$").get(()) 
} 

def companionMethod(clazz: Class[_], methodName: String) = { 
    getCompanion(clazz).getClass.getMethod(methodName).invoke(companion) 
} 

// Print all companion methods: 
println(getCompanion(classOf[A.B]).getMethods.map(_.getName).mkString("\n")) 

println(companionMethod(classOf[A], "bar") == 5) 
println(companionMethod(classOf[A.B], "foo") == 4) 
Смежные вопросы