Как сделать так, чтобы класс данных (Kotlin) расширялся от суперкласса и наследовал одно из полей суперкласса?

Я пытаюсь создать собственный метод toString() для некоторых из моих классов данных. Но я хотел бы определить переопределение fun toString только один раз.

Это будет мой суперкласс:

abstract class Id(val value: String) {
   override fun toString(): String {
       return value
   }
}

Теперь я хочу использовать настроенный метод toString() в некоторых моих классах данных, расширив идентификатор суперкласса:

data class MyId(val v: String): Id(v)

однако это приведет к появлению вторичного поля и геттера для «v» в MyId, а это не то, что мне нужно. Использование «значения» вместо «v» дает мне проблему: «значение» скрывает член супертипа «Id». Я хотел бы повторно использовать поле «значение» и геттер, определенные в Id. Я не хочу вводить новый.

Как я могу это исправить?


person Stijn Haezebrouck    schedule 13.06.2019    source источник


Ответы (3)


Я не совсем уверен, что вы пытаетесь сделать, но вы можете сделать это

abstract class Id(open val value: String) {
    override fun toString(): String {
        return value
    }
}

data class MyId(override val value: String): Id(value)
person Francesc    schedule 13.06.2019
comment
огромное спасибо. Ключевым моментом здесь было открытие значения в суперклассе. Видите ли, я новичок в Kotlin, и у меня еще нет рефлекса, чтобы явно открывать члены класса, которые мне нужны в подклассах. (В java члены класса открыты по умолчанию.) И потом, меня также смутил синтаксис, который одновременно определяет два члена класса (значение + геттер) и определяет аргумент конструктора + тот факт, что мне нужно открыть его - person Stijn Haezebrouck; 14.06.2019
comment
ясное намерение в вопросе - person Stijn Haezebrouck; 14.06.2019
comment
это не помогает: сам класс данных вводит реализацию toString(), переопределяющую реализацию суперкласса. В примере (MyId(avalue).toString()) будет получена строка MyId(avalue), а НЕ avalue. - person Stijn Haezebrouck; 23.06.2019

Обратите внимание, что для классов, отличных от data, вы можете просто удалить val вместо того, чтобы переопределять его:

class MyId(value: String): Id(value)

Это также не требует, чтобы value в Id было open.

Это недопустимо, когда MyId является классом данных, потому что все параметры его конструктора должны быть val или var.

person Alexey Romanov    schedule 14.06.2019

Что я хотел сделать в своем вопросе, так это переопределить метод toString() класса данных, создав суперкласс.

Это невозможно. Францеск, его решение не переопределяет метод toString() класса данных. Сгенерированный метод toString класса данных по-прежнему будет использоваться.

рассмотреть возможность:

  val myId = MyId("a string value")
  assertThat(myId.toString()).isEqualTo("MyId\"a string value\")")
  assertThat(myId.toString()).isNotEqualTo("a string value")

Единственный способ изменить метод .toString() класса данных — в самом классе данных:

data class MyId(val value: String) {
  override fun toString() = value
}
person Stijn Haezebrouck    schedule 23.06.2019