Классы данных Kotlin с суперклассом Java - PullRequest
0 голосов
/ 07 октября 2019

У меня есть класс Java, который содержит общую информацию о сущностях базы данных (то есть их идентификатор).

@Data
public class DbEntity {
    protected final String id;

    public DbEntity(String id) {
        this.id = id;
    }
}

Мы используем Lombok @Data для генерации геттеров, toString, equals ...

В Java я просто расширил бы этот класс и снова добавил @Data.

@Data
class JavaSubClass extends DbEntity {

    public JavaSubClass(String id) {
        super(id);
    }
}

В более новом сервисе мы используем Kotlin, но хотели бы повторно использовать стандартные классы, такие как DbEntity.

Мой первый подход состоял в том, чтобы просто объявить класс данных, такой как

data class SubClass1(val id: String, val name: String) : DbEntity(id)
Accidental override: The following declarations have the same JVM signature (getId()Ljava/lang/String;):
  fun <get-id>(): String defined in com.demo.SubClass1
  fun getId(): String! defined in com.demo.SubClass1

После некоторого чтения я нашел несколько решений, которыми я не очень доволен.

  1. Не используйте классы данных. Это работает, но оставляет мне задачу реализовать equals и т. Д.
class SubClass4(id: String, val name: String) : DbEntity(id)
Дублируйте поле. Это работает, но мы получаем два поля, которые могут быть не синхронизированы.
data class SubClass3(val subId: String, val name: String) : DbEntity(subId)
Присвойте получателю другое имя. Это в основном также дублирует поле, но скрывает геттер.
data class SubClass2(@get:JvmName("getId_") val id: String, val name: String) : DbEntity(id)

Как я уже сказал, я не доволен ни одним из решений, представленных выше. Вместо этого было бы лучше иметь абстрактный суперкласс или интерфейс. Однако класс Entity находится в библиотеке, от которой зависят в основном проекты Java. Я не решаюсь изменить его только из-за новой зависимости от Kotlin.

Кто-нибудь сталкивался с подобными проблемами и у них есть совет, как их решить?

1 Ответ

0 голосов
/ 07 октября 2019

В качестве обходного пути до тех пор, пока KT-6653 - свойства Kotlin не переопределяют методы получения и установки в стиле Java , я бы выбрал вариант вашей точки 3, то есть:

data class SubClass(@get:JvmName("bogusId") private val id: String, val name: String) : DbEntity(id)

Преимущество этого варианта в том, что вы всегда получаете доступ к "оригинальной" getId -функции. Вы не будете использовать функцию bogusId(), поскольку она невидима / недоступна (доступ к ней с помощью отражения не имеет смысла ... вас интересует только фактическое поле id). Это работает и выглядит одинаково для обеих сторон: как от Java, так и от Kotlin. Тем не менее, под капотом этот вариант использует 2 поля, но в лучшем случае вы можете просто заменить его в будущем на что-то вроде:

data class SubClass(override val id: String, val name : String) : DbEntity(id)
...