2016-11-19 62 views
0

我想创建一个封闭的宇宙类,其中每个子类是一些外部类的内部类。我以为我可以使用密封的内部类层次结构的基础上,像这样:密封的内部类

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的实例数据。

一个解决办法,我发现是使InnerBasesealed

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子类都不再是封闭的。

回答

0

也许你错过了一个静态的地方?因为你不想实例化一个类来使用它们的内部。

当然,我并不像Kotlin那样精通,所以我可能会犯错。

+0

是的,但是'Inner'不能是静态的,因为它需要访问'Outer'的'foo'字段。 – Cactus

1

如果我正确地理解了你,你不需要存储Outer的实例,就像存储“staticfoo的地方一样。那么你需要object s,而不是class es。

我换成class Outerobject 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() 
    } 
} 
+0

那么在我的真实程序中,'Outer'中还有很多其他事情发生,而且我确实打算拥有它的多个实例。 – Cactus

1

技术上你正在尝试做的是这样的:

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

它提供Inner1Outer的实例,不需要的Inner实例。我不知道有任何干净的方式在Kotlin做这件事

+0

是的,我想将'outer'隐式地传递给'Inner1'。那么没有办法做到这一点?在那种情况下,我想我宁愿选择开放式继承解决方案。 – Cactus

+0

如果'Inner'是一个枚举,那么这是可能的 – voddan