¿Es posible crear un tipo de function recursiva en Kotlin?

Tengo funciones que representan pasos en un process. Cada function también conoce el siguiente paso, si hay uno. Me gustaría poder hacer algo como:

fun fooStep() : Step? { ... do something ... return ::barStep // the next step is barStep } 

Estas funciones se llaman desde una function central de despacho, que contiene un código como este:

 var step = startStep while (step != null) { step = step() } 

Tenga en count que la lógica en un paso particular también determina el siguiente paso, si es que hay uno.

Pensé que podría definir Step como:

 typealias Step = () -> Step? 

Entonces un Step es una function que devuelve otro Step o nulo. Sin embargo, esto no se puede comstackr con:

 Kotlin: Recursive type alias in expansion: Step 

Puedo evitar esto envolviendo la function en un object. p.ej:

 data class StepWrapper(val step: () -> StepWrapper?) 

y cambiando mis firmas de funciones en consecuencia.

Desafortunadamente, esto significa que no puedo usar ::barStep funciones (por ej .: ::barStep ), sino que tengo que envolverlas en un StepWrapper :

 fun fooStep() : StepWrapper? { ... do something ... return StepWrapper(::barStep) } 

(También tengo que cambiar mi ciclo de envío, en consecuencia).

Me gustaría evitar la necesidad de crear estos objects de envoltura, si es posible. ¿Hay alguna manera de hacer esto en Kotlin?

Puede definirlo utilizando una interfaz genérica:

 interface StepW<out T> : ()->T? interface Step : StepW<Step> class Step1 : Step { override fun invoke(): Step? = Step2() } class Step2 : Step { override fun invoke(): Step? = null } 

Donde Step es su tipo de function recursiva.

Así es cómo puedes hacer que funcione, aunque realmente no estoy seguro de lo que intentas lograr con él:

 typealias Fun<T> = () -> T typealias Step<T> = () -> (T) typealias Step1 = Step<Fun<Step2>> typealias Step2 = Step<Fun<Step3>> typealias Step3 = Step<Unit> fun step1(): Step1 { return { println("step 1") ::step2 } } fun step2(): Step2 { return { println("step 2") ::step3 } } fun step3(): Step3 { return { println("done") } } 

Use un Enum para implementar el patrón de estado con estados finitos y prefiera devolver valores que no sean nulos. Una enumeración puede henetworkingar de una function.

 enum class Step : () -> Step { Step1 { override fun invoke() = Step2 }, Step2 { override fun invoke() = End }, End { override fun invoke() = this } } fun work() { var step = Step.Step1 while (step !== Step.End) { step = step() } } 
  • kotlin usando types generics de class de datos
  • RxKotlin - Single.just () no se emite al suscribirse TestSubscriber
  • Emitir cualquiera a Matriz en Kotlin
  • Kotlin - Constructor secundario de class con parámetro diferente
  • Kotlin en Android: ¿hay un requisito mínimo de nivel de API?
  • Enfoque correcto para la class de Kotlin inyectada de constructor inmutable
  • ¿Cómo se ejecuta el método de suspensión a través de la reflexión?
  • ¿Cómo hacer que una class de datos en Kotlin sea inmutable con el object Date de Java en ella?
  • Firebase-Firerestre no puede usar dos documentos
  • Android: Kotlin con Dagger
  • Error de statement de function al comstackr con Kotlin 12