在实现接口

时间:2018-05-25 08:12:51

标签: interface kotlin

假设我有一个接口,它提供许多带有默认getter的不可变属性,就像这样

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")
    } 
}

现在,有几个具体实现只使用大多数默认值。但是,我还想提供一个ConfigurableRepository,以便在其他想要在运行时根据其他用户参数进行配置的项目中提供更大的灵活性。

如何创建具有可选参数的主构造函数?

我希望有以下几点:

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

编辑澄清

这里的目的是使用主构造函数行为,其中命名参数是可选的。更具体地说,namepatternurl对于调用构造函数的任何人都是可选的,它将默认为接口的getter。但是,我显然试图强迫Kotlin interface适应这个模型,这可能是一个菜鸟Kotlin的用户错误,因为我最终无法访问超级。

来自class docs

  

实际上,用于声明属性并从中初始化它们   主要构造函数,Kotlin有一个简洁的语法:

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

我似乎遇到错误,这会隐藏超类型的成员并需要override修饰符。如果我尝试覆盖超类型然后提供默认值,它会抱怨在这种情况下无法访问超类型。

这只能在具有可变性的辅助构造函数中完成     值吗

我也对提供支持超常规配置的接口的更好方法的建议/反馈持开放态度。最重要的方面是接口始终为约定提供默认值。或者,更简单地说:

有更好的方法吗?

4 个答案:

答案 0 :(得分:1)

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

特别是围绕类和接口的第2段。

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

   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() {

        }
    }

答案 1 :(得分:1)

由于我现在想出了如何使用var来解决问题,所以这里是您问题中确切界面的答案。

class ConfigurableRepo(
        private var _name: String,
        private var _pattern: String,
        private var _url: String) : Repository 
{
    override val name get () = _name

    override val pattern get () = _pattern

    override var url
        get () = _url
        set (u: String) { _url = u }
}

答案 2 :(得分:1)

使用这样的抽象类:

abstract class Repository {
    open val name = "default"
    open val pattern = "default"
    open val url = "default"
}

// example: only override name
class RepoWithDifferentName(
    override val name: String
): Repository() {
   // ...
}

答案 3 :(得分:0)

如果您的目的是为默认构造函数的参数设置默认值(伪编码,不编译):

class ConfigurableRepo (
        override val name: String,
        _url: String? = null,
        _pattern: String? = null
): Repository {
    override val pattern = _pattern ?: super.pattern
    override var url = _url ?: super.url

    // ... more code ...
}

然后前进的方法是“null as default pattern”,当方法声明中无法表达所需的默认值时,可以使用该模式。在你的情况下,它可以像这样工作:

val

正如您所看到的,该技巧适用于var以及name属性和字段。在接口中没有默认值的属性.tvs { display: flex; justify-content: space-between; align-items: center; padding: 1rem; } 在此类中使用直接字段实现。

相关问题