Ссылка вне запечатанного класса в Kotlin?
Я пытаюсь создать класс, который использует свое собственное состояние для работы с состоянием внешнего объекта, на который он ссылается. Внешний объект может быть класса A или B, которые похожи, но не контролируются автором. Таким образом, запечатанный класс создается для доступа к их общим атрибутам, согласно этому более раннему ответу от @ 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 с одинаковой кодовой базой; а также
- отмечая, что, хотя инструменты ABTool одинаковы, способ их применения для добавления магии немного отличается в A и B, так же как и доступ к концептуально общим элементам A и B может отличаться.
Есть мысли об этом или аналогичном обходном пути? Может быть, более функциональный подход, который я еще не задумал?
2 ответа
Если ABTool
быть закрытым классом - это то, от чего можно отказаться, вот решение:
- замещать
sealed
сinner abstract
наABTool
заявление; - отметка
BoxA
а такжеBoxB
как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
как внутренний, двигаться BoxA
а также BoxB
из этого в сферу ABTool
)
Альтернативой было бы добавить 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
сам и поэтому вы можете удалить его оттуда и сделать это val
в BoxA
а также BoxB
,