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?
An alternative would be to add an
ABTool
field toAB
:and pass
this
when creating it fromABTool
. That's just whatinner
really does, after all.In this specific case the field happens to be unused in
AB
itself and so you can remove it from there and make itval
inBoxA
andBoxB
.If
ABTool
being a sealed class is something you can give up, then here's a solution:sealed
withinner abstract
at theABTool
declaration;BoxA
andBoxB
asinner
as well;(alternatively, instead of marking
AB
as inner, moveBoxA
andBoxB
out of it to the scope ofABTool
)