打破或继续跨越阶级边界kotlin跳跃

是任何人面临这个问题。 break or continue jump across class boundary kotlin

这个问题出现在我打算使用break或continue的时候。 里面的lambda与接收器我创建'letIn'

与接收器代码的lambda

 fun letIn(componentName: String?, values: List<LifeService.Value?>?, body: (String, List<LifeService.Value?>) -> Unit) { if (!TextUtils.isEmpty(componentName) && (values != null && values.isNotEmpty())) { body(componentName!!, values) } } 

这个示例代码。

 for (option in 0 until optionsSize) { val component = optionsGroup?.options?.get(option) component?.let { with(component) { letIn(presentation, values, { componentName, values -> if (componentName == LifeComponentViewType.CHECKBOX) { letIn(transformCheckBoxValues(optionsGroup), { data -> dataSource?.push(componentName, ComponentDataCheckBoxCollection(name, data)) view.buildComponent(componentName) // break or continue didnt work }) } else { dataSource?.push(componentName, ComponentDataCollection(name, values)) view.buildComponent(componentName) } }) } } } 

因为上面的代码没有工作,所以我使用命令的方式。

 for (option in 0 until optionsSize) { val component = optionsGroup?.options?.get(option) if (component != null) { val presentation: String? = component.presentation val values = component.values if (!TextUtils.isEmpty(presentation)) { if (presentation == LifeComponentViewType.CHECKBOX) { val data = transformCheckBoxValues(optionsGroup) if (data.isNotEmpty()) { dataSource?.push(presentation, ComponentDataCheckBoxCollection(optionsGroup.name, data)) view.buildComponent(presentation) return } } else { dataSource?.push(presentation!!, ComponentDataCollection(component.name, values)) view.buildComponent(presentation!!) } } else { return } } } 

有没有人有建议?

(抛开其他编码错误)您看到错误,因为在您的lambda中,您不能使用breakcontinue跳出lambda到最近的循环。 相反,您可以使用合格的return从lambda跳转到标签。

参考语言参考

return-expression从最近的封闭函数 (即foo)返回。 (请注意,只有传递给内联函数的lambda表达式才支持这种非本地返回。)如果我们需要从lambda表达式返回,则必须标记它并限定返回

(强调我的)

你的第二个例子显示你希望你的lambdas从封闭函数做一个非本地返回。 因此,您不需要限定您的return ,但是您的函数letIn必须inline声明(否则您只能执行本地合格的退货)。

 inline fun letIn(componentName: String?, values: List<LifeService.Value?>?, body: (String, List<LifeService.Value?>) -> Unit) { if (!TextUtils.isEmpty(componentName) && (values != null && values.isNotEmpty())) { body(componentName!!, values) } } 

…或者如果你想要它有接收器…

 inline fun String?.letIn(values: List<LifeService.Value?>?, body: String.(List<LifeService.Value?>) -> Unit) { if (!TextUtils.isEmpty(this) && (values != null && values.isNotEmpty())) { this!!.body(values) } } 

当你声明letIninline ,你可以在你的lambda表达式中放入return ,而不需要编译器抱怨。 你的函数不需要inline如果你的lambdas只做本地返回,但是它需要有一个合格的返回值(比如return@letIn )。

你的第一个例子会看起来像这样…

 for (option in 0 until optionsSize) { val component = optionsGroup?.options?.get(option) component?.let { with(component) { presentation.letIn(values, { values -> if (this == LifeComponentViewType.CHECKBOX) { this.letIn(transformCheckBoxValues(optionsGroup), { data -> dataSource?.push(this, ComponentDataCheckBoxCollection(this, data)) view.buildComponent(this) return //returns from function }) } else { dataSource?.push(this, ComponentDataCollection(name, values)) view.buildComponent(this) return //returns from function } }) } } } 

最后,请注意,如果你想早点跳出lambda表达式,但是继续一个外部循环,如下所示:

 fun test1() { val list = listOf("a", "b", "c") val optionsSize = 2 for(i in 0..optionsSize) loop@ { println("calliing list.forEach") list.forEach lit@ { if(it == "a") return@lit if(it == "c") return@loop println(it) } } } 

它不会工作。 Intelli-sense不会抱怨,但编译器会引发内部错误。 但是你可以将外部循环转换为lambda,并且它可以工作。

 fun test() { val list = listOf("a", "b", "c") val optionsSize = 2 (0..optionsSize).forEach() loop@ { println("calliing list.forEach") list.forEach lit@ { if(it == "a") return@lit if(it == "c") return@loop println(it) } } } 

同样,这只适用于lambda传递的函数声明为inline (如forEach声明为inline )。