Home Articles

属性获取器在Supertype上键入,而不是在Kotlin中实现

Asked
Viewed 981 times
5

假设我有两个类,一个 Base 和一个 Impl ,它扩展了 Base .

package mypackage

open class Base
class Impl : Base()

我如何用 public getter typed as the Base-Type 创建 private property for the concrete Impl-Type (for internal use) 来实现多态?我最初的方法是这样的:

class Test {
    private val myType = Impl()
        get():Base
}

但是,Kotlin编译器抱怨:

错误:(30,11)Kotlin:Getter返回类型必须等于属性的类型,即'mypackage.Impl'

基本上,这就是普通Java中的样子:

public class Test {
    private Impl myImpl = new Impl();

    public Base getBase() {
        return myImpl;
    }
}

怎么能实现这个目标?我错过了什么吗?

附:我知道Backing Fields和创建自定义方法作为getter的解决方法,我只是好奇如何以优雅的Kotlin方式处理它 .

2 Answers

  • 6

    您将使用两个不同的属性对此进行编码,就像在Java中一样 . 除非你对 Impl 没关系,否则永远不会专攻这个课程 . 所以这里有很多选择:

    // if you don't need Impl typed as Impl then just hold it as base
    class Test1 {
        public val base: Base = Impl()
    }
    
    // have both with pointing one reference at the other
    class Test2 {
        private val _impl = Impl()
        public val base: Base = _impl
    }
    
    // have both, second one is a getter (no real benefit over Test2)
    class Test3 {
        private val _impl = Impl()
        public val base: Base
           get() = _impl
    }
    
    // use a function to do basically a cast
    class Test4 {
        private val _impl = Impl()
        public fun asBase(): Base = _impl
    }
    

    或者不要担心这个其他属性,任何使用抓取Impl都可以将其保存为类型Base:

    class Test5 {
        public val impl: Impl = Impl()
    }
    
    // later
    val thing: Base = Test5().impl
    

    也许您希望以一种具有通用接口的方式构建它以获得基本实现?

    open class Base {}
    
    // a common way to get the implementation from within a class
    interface Based {
        val base: Base
    }
    
    class ImplAbc : Base()
    class ImplXyz : Base()
    
    class TestAbc : Based {
        override val base: Base = ImplAbc()
    }
    
    class TestXyz : Based {
        private val _impl = ImplXyz()
        override val base: Base = _impl
    }
    
  • 1

    如果 property 是私人的,那么吸气剂也是如此 . 在这种情况下,它将具有什么类型并不重要 . 如果您想拥有基本类型的公共属性,则需要单独声明它:

    private val _myType = Impl()
    
    public val myType : Base
        get() = _myType
    

Related