Ссылка вне запечатанного класса в 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 быть закрытым классом - это то, от чего можно отказаться, вот решение:

  1. замещать sealed с inner abstract на ABTool заявление;
  2. отметка 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,

Другие вопросы по тегам