Делегирование конструктора Котлина во внутренний класс данных?

У нас есть абстрактный Java-класс (который мы не можем изменить), называемый AbstractClass который мы хотим реализовать в Котлине. Требование – реализация Kotlin сериализуется / десериализуется в JSON с использованием ванильного Jackson Databind . Это привело нас к следующей реализации:

 class MyClass(private val data: MyClassData? = null) : AbstractClass<MyClassData>(MyClass::class.java, "1") { data class MyClassData(var name: String = "", var age: Int = 0) : AbstractData override fun getData(): MyClassData? { return data } } 

Этот класс всегда будет использоваться с Java, и в настоящее время вы можете создать его таким образом (Java):

 MyClass myClass = new MyClass(new MyClassData("John Doe", 25)); 

Но мы предпочли бы создать его таким образом:

 MyClass myClass = new MyClass("John Doe", 25); 

Я могу, конечно, изменить код Котлина на что-то вроде этого:

 class MyClass(@JsonIgnore private var name: String = "", @JsonIgnore private var age: Int = 0) : AbstractClass<MyClassData>(MyClass::class.java, "1") { data class MyClassData(var name: String = "", var age: Int = 0) : AbstractData private var data : MyClassData? = null init { data = MyClassData(name, age) } override fun getData(): MyClassData? { return data } } 

но это очень многословное и своеобразное поражение в целях использования Kotlin.

Я думаю, что я хотел бы сделать что-то вроде этого (псевдокод):

 class MyClass(private val data: MyClassData? = null by MyClassData) : AbstractClass<MyClassData>(MyClass::class.java, "1") { data class MyClassData(var name: String = "", var age: Int = 0) : AbstractData override fun getData(): MyClassData? { return data } } 

(обратите внимание на by MyClassData в конструкторе MyClass который, очевидно, не работает)

Т.е. я хотел бы как-то уничтожить или делегировать конструктор MyClass, чтобы принять те же аргументы, что и MyClassData, не дублируя их. Это то, что вы можете сделать в Котлине, или есть другой способ решить проблему, не добавляя слишком много кода?

Я думаю, что ваши основные проблемы: (a) сжатый внешний API, (b) чистое внутреннее состояние (для Джексона)

Вторичный конструктор

Это довольно скудно:

 class MyClass internal constructor(private val data: MyClassData) : AbstractClass<MyClass>(MyClass::class.java, "1") { data class MyClassData(var name: String, var age: Int) : AbstractData constructor(name: String, age: Int) : this(MyClassData(name, age)) override fun getData(): MyClassData? = data } 

Простой API без создания дополнительных полей (хотя я думаю, что этот синтаксис вводит в заблуждение):

 val myClass = MyClass("John Doe", 25) 

Pass-Thru Params & Initializer:

Это была моя первая идея: прямо вытащить параметры внешнего класса (хотя теперь я думаю, что вторичный конструктор лучше, поскольку он не загрязняет внешний класс):

 class MyClass(@JsonIgnore private val name: String, @JsonIgnore private val age: Int) : AbstractClass<MyClass>(MyClass::class.java, "1") { data class MyClassData(var name: String, var age: Int) : AbstractData private val data = MyClassData(this@MyClass.name, this@MyClass.age) override fun getData(): MyClassData? = data } 

… опять же, тот же API:

 val myClass = MyClass("John Doe", 25) 

Self-Factory

Этот подход имеет потенциально более описательный синтаксис:

 class MyClass(private val data : MyClassData) : AbstractClass<MyClass>(MyClass::class.java, "1") { data class MyClassData(var name: String, var age: Int) : AbstractData companion object Factory { fun create(name: String, age: Int) = MyClass(MyClassData(name, age)) } override fun getData(): MyClassData? = data } 

Это можно назвать следующим:

 val myClass = MyClass.Factory.create("John Doe", 25) 

Концептуальный синтаксис: структурирование (НЕ СУЩЕСТВУЕТ)

Мне нравится идея синтаксиса «structuring» для аргументов метода, которые группируют входные данные в объект (противоположность деструктуризации); немного похоже на varargs (т.е. синтаксический сахар):

 class MyClass( private val data: (name: String, age: Int) : MyClassData(name, age) ) { ... } 

Это можно было бы назвать одним из двух способов:

 val myClass1 = MyClass(MyClassData("John Doe", 25)) val myClass2 = MyClass("John Doe", 25) 

На практике это редкое требование и легко управляемое с явными перегрузками всего за несколько лишних символов, поэтому я не думаю, что это когда-нибудь произойдет.

Intereting Posts
Kotlin – Как импортировать пакеты узлов? com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: ожидается BEGIN_ARRAY, но был STRING в строке 1 столбца 2 пути Ошибка несоответствия данных типа Kotlin Невозможно запустить сканирование покрытия (Java / Kotlin / Gradle 3.3 на Windows и Travis) Как я могу создать проект Kotlin, который строится вместе с Gradle? Является ли ключевое слово lateinit ненужным? Создать ArrayList <String> из строки-массива ресурсов kotlin-android null не может быть отличен для непустого типа kotlin.String Как смешивать ScatterChart с горизонтальными и вертикальными линиями Есть ли способ написать функцию расширения, которая изменяет значение объекта? Как извлечь kotlin-react html в метод Инициализация Kotlin val, когда Не удается отладить обработчик аннотации при использовании kapt и gradle Получить загрузчик классов generics для разбора вложенного поля Parcelable generic getFragmentManager () не работает в Котлине