Если никто больше не приходит с рабочим ответ, я не думаю, что это было бы все, что трудно написать генератор кода на основе сигнатур методов.
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(_ != '('))
будет получать подписи и имя функции, соответственно. Затем нам нужно преобразовать примитивные типы, которые довольно легко, так как нам просто нужно заглавной буквы (за исключением пустоты, которая становится блок):
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)
}
(переменные аргументы не работают здесь, кстати - you'd нужно, чтобы исправить их, если они присутствовали Вы можете сделать это, возвращаясь к методу .isVarArgs
от самого метода (а не его строковое представление.) и преобразование последнего массива [X] в X *, а затем называет его ai: _*
.)
Приятная вещь в этом подходе состоит в том, что если существуют общие методы, вам даже не нужно использовать структурную типизацию в порядке вытащить их - вы можете определить свою собственную черту, которую наследуют ваши обернутые методы! (И если вы особенно амбициозны, вы можете обучать практически, но не совсем соответствующие методы, чтобы фактически соответствовать, например, для всех, имеющих одинаковое имя метода.)
Впечатляет! Действительно, это экономит некоторую типизацию, спасибо. –
Из-за отсутствия рабочего ответа на исходный вопрос, я принимаю ваш ответ. –