【问题标题】:Sealed inner classes密封的内部类
【发布时间】:2016-11-19 08:49:39
【问题描述】:

我想创建一个封闭的类世界,其中每个子类都是某个外部类的内部类。我以为我可以使用密封的内部类作为层次结构的基础,如下所示:

class Outer {
    fun foo(): Int {
        // ...
    }

    inner sealed class InnerBase(val i: Int) {
        fun sharedFunctionality() {
            println(foo() + i)
        } 

        abstract fun doIt()

        inner class Inner1: InnerBase(1) {
            override fun doIt() {
                blah()
                sharedFunctionality()
                bloo()
            }
        }
    }
}

注意

  • Outer 是一个合适的类,它可以有许多不同的实例。每个实例都应该能够创建Inner1 将调用正确的foo
  • InnerBase 子类的宇宙是有限的
  • InnerBase 有一些实例方法,供各种Inner 子类使用,它访问Outer 的非静态方法foo
  • InnerBase 的具体子类(例如Inner1)将参数传递给InnerBase 的构造函数

但是,问题在于我不知道如何在Outer 中构造Inner1 类型的值。我希望这会奏效:

class Outer { // continued from above
    fun someMethod() {
        val x: InnerBase = InnerBase.Inner1()
    }
}

但这失败了

src/InnerSealed.kt:14:27: error: unresolved reference: Inner1
    val x : InnerBase = InnerBase.Inner1()
                                 ^

我想问题在于Inner1 实际上是Inner 的内部类,所以我需要Inner 的实例才能构造Inner1 的实例。但是,这不是我想要的;我希望Inner 只是我的Inner1 等类的基类,具有一些在所有子类之间共享并访问Outer 的实例数据的功能。

我发现的一种解决方法是将InnerBase 设为非sealed

class Outer {
    fun foo(): Int {
        // ...
    }

    inner abstract class InnerBase(val i: Int) {
        fun sharedFunctionality() {
            println(foo() + i)
        }

        abstract fun doIt()
    }

    inner class Inner1: InnerBase(1) {
        override fun doIt() {
            sharedFunctionality()
        }
    }

    fun someMethod() {
        val x : InnerBase = Inner1()
    }
}

但随后InnerBase 的子类不再关闭。

【问题讨论】:

    标签: java inheritance scope kotlin inner-classes


    【解决方案1】:

    如果我理解正确,您不需要Outer 的实例,而是需要一个存储“staticfoo 的地方。那么你需要objects,而不是classes。

    我将class Outer 替换为object Outer 并删除了sealed

    object Outer {
        var foo = 42
    
        sealed class Inner(val i: Int) {
            init {
                println(foo + i)
            }
    
            class Inner1: Inner(1)
        }
    
        init {
            val x: Inner = Inner.Inner1()
        }
    }
    

    【讨论】:

    • 嗯,在我的真实程序中,Outer 中发生了很多其他事情,我确实计划有多个实例。
    【解决方案2】:

    从技术上讲,您要做的是:

    class Outer {
        var foo = 42
        init {
            val x: InnerBase = InnerBase.Inner1(this)
        }
    
        sealed class InnerBase(val outer: Outer, val i: Int) {
    
            fun sharedFunctionality() {
                println(outer.foo + i)
            } 
    
            abstract fun doIt()
    
            class Inner1(outer: Outer): InnerBase(outer, 1) {
                override fun doIt() {
                    sharedFunctionality()
                }
            }
        }
    }
    

    它为Inner1 提供Outer 的实例,但没有Inner 的实例。我不知道在 Kotlin 中有任何干净的方法

    【讨论】:

    • 是的,确切地说,我想将outer 隐式传递给Inner1。那么有没有办法做到这一点?在这种情况下,我想我宁愿使用开放继承解决方法。
    • 如果Inner 是一个枚举你是可能的
    【解决方案3】:

    也许您在某处遗漏了静态元素?因为你不想实例化一个类来使用它们的内部。

    当然,我对 Kotlin 的熟练程度不高,所以我可能大错特错。

    【讨论】:

    • 是的,但是Inner 不能是静态的,因为它需要访问Outerfoo 字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多