2

I'm trying to create a class that uses its own state to operate on the state of an external object that it holds a reference to. The external object can be of class A or B, which are similar, but not controlled by the author. So a sealed class is created to access their common attributes, per 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}"
}

The problem now is that I've figured out I can't operate on the external object in the way I want, because a sealed class can't refer to its outer class members. Is there a better way to make this work, even if using a different approach (other than sealed class), while:

  • not changing foreign classes A or B;
  • respecting that A and B (and many others in the real case) are similar, so I'm trying to write one tool that calculates and adds magic to A and B with the same code base; and
  • noting that although the ABTool tools are the same, the way they are applied to add magic is slightly different in A vs. B, just as the to access the conceptually common elements of A and B may be different.

Any thoughts on this or a similar workaround? Maybe a more functional approach that I haven't conceived yet?

4

2 回答 2

2

如果ABTool您可以放弃成为密封类,那么这里有一个解决方案:

  1. 在声明处替换sealed为;inner abstractABTool
  2. 标记BoxABoxB以及inner

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

于 2017-11-18T01:01:26.087 回答
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在从创建它时传递ABToolinner毕竟,这就是真正的作用。

在这种特定情况下,该字段本身恰好未使用AB,因此您可以从那里将其删除并val放入BoxAand中BoxB

于 2017-11-18T05:17:08.600 回答