7

我有代表流程中步骤的函数。每个函数也知道下一步,如果有的话。我希望能够做类似的事情:

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

这些函数是从一个中央调度函数调用的,它包含的代码有点像这样:

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

请注意,特定步骤中的逻辑也决定了下一步(如果有的话)。

我以为我可以定义Step为:

typealias Step = () -> Step?

所以 aStep是一个返回另一个Step或 null 的函数。但是,这无法编译:

Kotlin: Recursive type alias in expansion: Step

我可以通过将函数包装在一个对象中来解决这个问题。例如:

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

并相应地更改我的函数签名。

不幸的是,这意味着我不能只使用函数文字(例如:)::barStep,而是必须将它们包装在 a 中StepWrapper

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

(我还必须相应地更改我的调度循环。)

如果可能的话,我想避免创建这些包装对象。在 Kotlin 中有没有办法做到这一点?

4

3 回答 3

2

您可以使用一些通用接口来定义它:

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
}

Step您的递归函数类型在哪里。

于 2017-06-09T23:00:45.157 回答
0

尽管我真的不确定您要使用它实现什么目标,但您可以通过以下方式使其工作:

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") }
}
于 2017-06-10T15:59:43.197 回答
0

使用Enum来实现具有有限状态的状态模式,并且更喜欢返回非空值。枚举可以从函数继承。

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()
    }
}
于 2017-06-12T22:31:52.857 回答