在Kotlin的密封课堂外参考?

时间:2017-11-18 00:38:10

标签: kotlin abstract-class inner-classes sealed data-class

我试图创建一个类,该类使用自己的状态来操作它拥有引用的外部对象的状态。外部对象可以是A类或B类,它们类似,但不受作者控制。因此,根据this earlier answer from @SimY4创建一个密封类来访问它们的公共属性。

// *** DOES NOT COMPILE ***
class A {   // foreign class whose structure is not modifiable
  val prop get()= "some string made the Class-A way"
}
class B {   // foreign class whose structure is not modifiable
  val prop get()= "some string made the Class-B way"
}
data class ABTool (val obj:AB, val i:Int, val j:Int) {
  // class that manipulates i and j and uses them to do
  // things with AB's "common" attributes through the sealed class AB
  sealed class AB {   // substitute for a common interface
    abstract val prop: String
    abstract val addmagic: String
    data class BoxA(val o:A) : AB() {
      override val prop get()= o.prop
      override val addmagic get() = prop + this@???.magic  // HOW TO REFERENCE?
    }
    data class BoxB(val o:B) : AB() {
      override val prop get()= o.prop
      override val addmagic get() = this@???.magic + prop  // HOW TO REFERENCE?
    }
  }
  val magic get()= "magic: ${i*j}"
}

现在的问题是,我已经发现我无法以我想要的方式对外部对象进行操作,因为密封的类无法引用其外部类成员。有没有更好的方法来使这项工作,即使使用不同的方法(密封类除外),同时:

  • 不改变外国班A或B;
  • 尊重A和B(以及实际案例中的许多其他内容)是相似的,所以我试图编写一个工具来计算并添加具有相同代码库的A和B的魔法;和
  • 注意到尽管ABTool工具是相同的,但它们在添加魔法方面的应用方式在A与B之间略有不同,正如访问A和B的概念上常见的元素可能会有所不同。

对此或类似解决方法的任何想法?也许我还没有想到一个更实用的方法呢?

2 个答案:

答案 0 :(得分:2)

如果ABTool是一个密封的课程,你可以放弃,那么这是一个解决方案:

  1. sealed声明中将inner abstract替换为ABTool;
  2. BoxABoxB标记为inner;
  3. data class ABTool(val obj: AB, val i: Int, val j: Int) {
        inner abstract class AB {
            abstract val prop: String
            abstract val addmagic: String
    
            inner class BoxA(val o: A) : AB() {
                override val prop get() = o.prop
                override val addmagic get() = prop + magic
            }
    
            inner class BoxB(val o: B) : AB() {
                override val prop get() = o.prop
                override val addmagic get() = magic + prop
            }
        }
    
        val magic get() = "magic: ${i * j}"
    }
    

    (或者,不要将AB标记为内部,而是将BoxABoxB移出ABTool

    的范围。

答案 1 :(得分:1)

另一种方法是将ABTool字段添加到AB

sealed class AB(val tool: ABTool) {
  abstract val prop: String
  abstract val addmagic: String
  data class BoxA(val o:A, tool: ABTool) : AB(tool) {
    override val prop get()= o.prop
    override val addmagic get() = prop + tool.magic
  }
  data class BoxB(val o:B, tool: ABTool) : AB(tool) {
    override val prop get()= o.prop
    override val addmagic get() = tool.magic + prop
  }
}

并在this创建时传递ABTool。毕竟,这正是inner真正做的事情。

在这种特定情况下,该字段恰好在AB本身中未使用,因此您可以将其从那里删除,并在valBoxA中将其BoxB。 / p>