Kotlin тип безопасных строителей - PullRequest
0 голосов
/ 11 сентября 2018

В своем коде я использую шаблон Kotlin "type-safe builder":

insteadOf("search", "forest|ground") {
    println("Do something.");
}

Однако я также использую Kryo для сериализации данных (сохранения игры), и Kryo не нравитсяанонимный тип:

call: () -> Unit

Поэтому мне пришлось ввести интерфейс «Do» вместо вышеуказанного типа.Но теперь мой код выглядит намного ужаснее:

insteadOf("search", "forest|ground", object : World.InsteadOf.Do {
     override fun invoke() {
          println("Do something")
     }
})

Как я могу использовать простой {} - синтаксис с Do-интерфейсом?

РЕДАКТИРОВАТЬ:

Вот некоторые пояснения.

Я в некотором замешательстве (не новость).

Фактическое сообщение об ошибке Kryo, похоже, касается конструктора без аргументов, однако сразу после этого оноговорит: «Это анонимный класс, который в Kryo по умолчанию не сериализуем».

Вот полное сообщение об ошибке:

Exception in thread "main" com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): fi.starstuff.rogue.World$insteadOf$1
    This is an anonymous class, which is not serializable by default in Kryo. Possible solutions: 1. Remove uses of anonymous classes, including double brace initialization, from the containing class. This is the safest solution, as anonymous classes don't have predictable names for serialization.
    2. Register a FieldSerializer for the containing class and call FieldSerializer#setIgnoreSyntheticFields(false) on it. This is not safe but may be sufficient temporarily. Use at your own risk.
Serialization trace:
call (com.mygame.World$InsteadOf)
insteadOfs (com.mygame.World)
    at com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy.newInstantiatorOf(Kryo.java:1319)
    at com.esotericsoftware.kryo.Kryo.newInstantiator(Kryo.java:1127)
    at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1136)

Вот класс ВместоOf:

class InsteadOf {
        var verbs: Array<String> = arrayOf()
        var nouns: Array<String> = arrayOf()
        var where: String = ""
        var call: (() -> Unit)? = null
    }

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

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

  1. Очевидно, добавьте его
  2. используйте no-arg плагин компилятора для указания нужного классадополнительный конструктор org.jetbrains.kotlin:kotlin-noarg

Многие связанные с сериализацией библиотеки вынуждают пользователя иметь конструктор без аргументов. 'Существует проблема в kryo github.

Если ваша проблема не связана с no-arg - ваш вопрос будет дубликатом для this

0 голосов
/ 18 сентября 2018

Ну, я просто перешел на сериализацию ядра Java, и проблема ушла.

0 голосов
/ 11 сентября 2018

Вы можете в основном принять функцию () -> Unit в insteadOf и обернуть ее в Do экземпляр в теле:

fun insteadOf(foo: String, bar: String, call: () -> Unit) { 
    val doInstance = World.InsteadOf.Do(call)
    /* use doInstance */
}

Использование будет таким же, как в первом примере.

Также можно предоставить интерфейсу Do заводскую функцию, которая принимает () -> Unit и возвращает экземпляр Do.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...