Если никто не придет с рабочим ответом, я не думаю, что было бы так сложно написать генератор кода, основанный на сигнатурах метода.
val a = classOf[String].getMethods.map(_.toString).filter(s =>
s.contains("public") && s.contains("static")
)
будет, например,вытащите все сигнатуры метода (для String
в данном случае) в виде строк.Тогда
val b = a.map(_.split(" ").reverse.take(2).reverse)
получит только сигнатуру функции с типом возврата, разделенным спереди.Теперь
val c = b.map(_(1).dropWhile(_ != '(').drop(1).takeWhile(_ != ')').split(","))
val d = b.map(_(1).takeWhile(_ != '('))
получит подписи аргумента и имя функции соответственно.Затем нам нужно преобразовать примитивные типы, что довольно просто, поскольку нам просто нужно использовать заглавную букву в первой букве (за исключением void, который становится единицей):
def jprim2scala(s: String) = {
val prim = List("boolean","byte","short","char","int","long","float","double")
def arrayconvert(s: String): String = {
if (s.endsWith("[]")) "Array["+arrayconvert(s.substring(0,s.length-2))+"]"
else if (s=="void") "Unit"
else if (prim contains s) {
s.substring(0,1).toUpperCase + s.substring(1)
}
else s
}
arrayconvert(s)
}
def e = (b,c).zipped.map((bi,ci) => (jprim2scala(bi(0)), ci.map(jprim2scala)))
и, наконец, вы можете собрать все это вместе:
val f = (d,e).zipped.map((name,ei) => {
val (ret,args) = ei
val lastname = name.split('.').last
"def "+lastname+"(" +
(for ((a,i) <- args.zipWithIndex) yield ("a"+i+": "+a)).mkString(", ") +
"): "+ret+" = "+name+"("+(0 until args.length).map("a"+_).mkString(",")+")"
})
Теперь у вас есть набор кода Scala, который вы можете поместить (вручную) в соответствующий синглтон.
object Stringleton {
// The contents of this is cut-and-paste f.map(" "+_).foreach(println)
def valueOf(a0: java.lang.Object): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Array[Char]): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Array[Char], a1: Int, a2: Int): java.lang.String = java.lang.String.valueOf(a0,a1,a2)
def valueOf(a0: Boolean): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Char): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Int): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Long): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Float): java.lang.String = java.lang.String.valueOf(a0)
def valueOf(a0: Double): java.lang.String = java.lang.String.valueOf(a0)
def copyValueOf(a0: Array[Char], a1: Int, a2: Int): java.lang.String = java.lang.String.copyValueOf(a0,a1,a2)
def copyValueOf(a0: Array[Char]): java.lang.String = java.lang.String.copyValueOf(a0)
def format(a0: java.lang.String, a1: Array[java.lang.Object]): java.lang.String = java.lang.String.format(a0,a1)
def format(a0: java.util.Locale, a1: java.lang.String, a2: Array[java.lang.Object]): java.lang.String = java.lang.String.format(a0,a1,a2)
}
(Вараргс, кстати, здесь не работает -вам нужно исправить их, если они присутствуют. Вы можете сделать это, вернувшись к методу .isVarArgs
из самого метода (не его строкового представления) и преобразовав последний массив [X] в X *, а затем вызвав егоas ai: _*
.)
Хорошая особенность этого подхода в том, что если есть общие методы, вам даже не нужно использовать структурную типизацию для их извлечения - вы можете определить свою собственную чертучто ваши упакованные методы наследуют!(И если вы особенно амбициозны, вы можете использовать почти подходящие методы, чтобы соответствовать друг другу, например, чтобы все имели одно и то же имя метода.)