Kotlin - Restrict extension method scope

空扰寡人 提交于 2019-11-30 22:31:35

You can use a workaround with deprecated:

class Outer {
    fun middle(op: Middle.() -> Unit): Middle {...}

    @Deprecated("can not be used inside a Outer block", level = DeprecationLevel.ERROR)
    fun outer(op: Outer.() -> Unit): Outer = TODO()
}

class Middle {
    fun inner(op: Inner.() -> Unit): Inner {...}

    @Deprecated("can not be used inside a Middle block", level = DeprecationLevel.ERROR)
    fun middle(op: Middle.() -> Unit): Middle = TODO()
}

class Inner {
    @Deprecated("can not be used inside a Inner block", level = DeprecationLevel.ERROR)
    fun inner(op: Inner.() -> Unit): Inner = TODO()
}

Now the compiler will give you an error, and IDE will not suggest a wrong function in the completion:

outer {
    middle {
        inner {
            middle { }  // error
        }
    }
}

But you really should not do it for big DSLs. It is better to wait for https://youtrack.jetbrains.com/issue/KT-11551 as @KirillRakhman suggested.

Edit: After I fixed my example, it became much smaller. With one dummy function for a class it is not that much of boilerplate after all.

The official way to restrict scope is DslMarker. It cannot help in some cases (when you need to annotate java sources, for example) - and here @Deprecated is used. But try DslMarker first.

@DslMarker
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class Scope

@Scope
class Outer {
    fun middle(op: Middle.() -> Unit): Middle { /**/ }
}

@Scope
class Middle {
    fun inner(op: Inner.() -> Unit): Inner {/**/ }
}

class Inner

Thus the last middle call is not compilable anymore.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!