首页 > 解决方案 > Refer to super in default values of constructor parameters when implementing an interface

问题描述

Assume I have an interface that provides many immutable properties with default getters, as such

interface Repository {
    val name : String
    val pattern : String
        get() = "foo/bar/baz"
    var url : String
        get() = "http://mycompanyrepo.com/$name"

    fun add() {
        TODO("do something interesting here")
    } 
}

Now, there are several concrete implementations that just use most of the defaults. However, I also want to provide a ConfigurableRepository that allows for more flexibility in other projects that want to configure this at runtime, based on other user parameters.

How can I create a primary constructor that has optional parameters?

I was hoping something along the lines of:

class ConfigurableRepo(var name, var pattern, var url) {
   ...
}

Edited for clarification

The intent here is to use primary constructor behavior, where the named parameters are optional. More specifically, name, pattern, and url are all optional to anyone calling the constructor, and it will default to the interface's getters. But, I'm obviously trying to force the Kotlin interface to fit this model and it is probably a noob Kotlin user mistake, as I ultimately have no access to super here.

From the class docs

In fact, for declaring properties and initializing them from the primary constructor, Kotlin has a concise syntax:

class Person(val firstName: String, val lastName: String, var age: Int) {      
    // ...
}

I seem to be getting errors that this hides members of the supertype and requires the override modifier. If I try to override the supertype and then provide a default, it complains that supertypes aren't accessible in this context.

Can this only be done in a secondary constructor with mutable values?

I'm also open to suggestions/feedback on better ways to provide an interface that supports configuration over convention. The most important aspect being that the interface always provide defaults for a convention. Or, more simply put:

Is there a better way?

标签: interfacekotlin

解决方案


请查看 https://kotlinlang.org/docs/reference/visibility-modifiers.html

尤其是关于类和接口的第二段。

从这些示例中,如果您的情况可能,建议使用基类而不是接口。这看起来像这样:

   open class DefaultRepo {
        protected open val name = "foo/bar/baz"
        protected open val pattern = "foo/bar/baz"
        protected open val url = "http://mycompanyrepo.com/$name"

        open fun add() {
            TODO("do something interesting here")
        }
    }

    class RenamedRepo(newName: String): DefaultRepo() {
        override val name = newName
    }

    class ConfigurableRepo(n: String, p: String, u: String): DefaultRepo() {
        override val name = n
        override val pattern = p
        override val url = u

        override fun add() {

        }
    }

推荐阅读