2015-07-03 2 views
1

Я играл с Котлин, и я думаю, что было бы здорово иметь «функциональные классы», увидеть пример того, что я хочу:Обработка аннотации Kotlin: возможно ли генерировать метод расширения?

functional class MyStrFunction(val function: MyStrFunction.(String) -> String) { 
    val memory = HashMap<String, String>() 
    fun output(message: String) = println(message) 
} 

Идея заключается в том, что я смог бы использовать его как:

val f = MyStrFunction { 
    output("reversing $it"); 
    if (it in memory) 
     output(memory[it]) 
    return it.reverse() 
} 

Если бы я написать MyStrFunction, которую я хочу сам, полученный класс будет:

class MyStrFunction(val function: MyStrFunction.(String) -> String) { 
    val memory = HashMap<String, String>() 
    fun output(message: String) = println(message) 

    public fun invoke(s: String) = this.function(s) 
} 

Но это утомительно, чтобы написать это руками в каждом «функциональном классе».

Итак, вот мой вопрос: можно ли сделать functional аннотацию, а затем обработать ее, добавив invoke метод с желаемым кодом?

Я знаю, что kapt может использоваться для обработки аннотации Kotlin, но AFAIK пока не может генерировать код Kotlin, и нет возможности сделать функцию расширения в Java-коде.

Есть ли способ генерировать новый метод Kotlin для класса?

Node: Я понимаю, что идея функциональных классов имеет несколько вариантов использования, и что это не так трудно добавить упомянутый invoke метод вручную, но для меня это академический интерес к концепции обработки аннотаций в Котлине.

UPD: Просто мои мысли о функциональных классах: есть функция языка делегирования интерфейсов, и здесь это будет работать хорошо, но ссылка this не отображается в этом блоке. Пример:

class MyStrFunction(val function: MyStrFunction.(String) -> String) 
: (String) -> String by { this.function(it) } { // <-- won't compile :(
    val memory = HashMap<String, String>() 
    fun output(message: String) = println(message) 
} 
+0

Вы можете найти или добавить проблему в [YouTrack] (https://youtrack.jetbrains.com) с просьбой о создании функции KAPT для генерации Kotlin. Таким образом, вы сможете отслеживать прогресс для этой функции. –

ответ

3

Не уверен, что то, что вы хотите, можно сделать напрямую, однако это подход без «функциональных классов». Насколько я понимаю, вы хотите добавить функциональность к регулярной лямбда-функции. Во-первых, определить свою функциональность как обычный класс:

class Memory() { 
    val memory = hashMapOf<String, String>() 
    fun output(message: String) = println(message) 
} 

Затем определим вспомогательную функцию для привязки функции расширения к приемнику:

fun <T, R, E> T.bind(function: T.(R) -> E): (R) -> E = { this.function(it) } 

И затем использовать его как это

fun main(args: Array<String>) { 
    val mem = Memory() 

    val memoryFunction: Memory.(String) -> String = { 
     output("reversing $it"); 
     if (it in memory) 
      output(memory[it]) 
     it.reverse() 
    } 

    val function: (String) -> String = mem.bind(memoryFunction) 

    println(listOf("foo", "bar").map(function)) 
} 
+0

Спасибо, подход, который вы предлагаете, выглядит хорошо для этого случая. Но я все равно хотел бы сделать то же самое без избыточного и дублированного кода при использовании класса и, если возможно, даже без дополнительного кода в классе. – hotkey

Смежные вопросы