简体   繁体   中英

Sealed inner classes

I'd like to create a closed universe of classes, where each subclass is an inner class of some outer class. I thought I could use a sealed inner class for the base of the hierarchy, like so:

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

Note that

  • Outer is a proper class, which can have many different instances. Each instance should be able to create Inner1 's that will call the right foo
  • The universe of InnerBase subclasses is finite
  • InnerBase has some instance method, to be used by various Inner subclasses, which accesses Outer 's non-static method foo
  • The concrete subclasses of InnerBase (eg Inner1 ) pass arguments to InnerBase 's constructor

However, the problem with this is that I don't know how I can construct a value of type Inner1 in Outer . I was hoping that this would work:

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

but this fails with

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

I guess the problem is that Inner1 is actually an inner class of Inner , so I'd need an instance of Inner before I could construct an instance of Inner1 . However, this is not what I'd like; I'd like Inner to just be a base class for my Inner1 etc. classes, with some functionality which is shared between all subclasses and which access Outer 's instance data.

One workaround I've found is to make InnerBase non- 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()
    }
}

But then the subclasses of InnerBase are no longer closed.

If I understood you correctly, you don't need instances of Outer as much as a place to store " static " foo . Then you need object s , not class es.

I replaced class Outer with object Outer and removed 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()
    }
}

Technically what you are trying to do is this:

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

It provides Inner1 with an instance of Outer without an instance of Inner . I am not aware of any clean way of doing this in Kotlin

Maybe you are missing a static somewhere? As you don't want to instance a class to use their inner.

Granted I'm not as proficient in Kotlin so I may be horribly wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM