Reputation: 903
I use the Kotlin "type-safe builder" pattern in my code:
insteadOf("search", "forest|ground") {
println("Do something.");
}
However, I am also using Kryo to serialize data (save a game), and Kryo doesn't like the anonymous type:
call: () -> Unit
So I had to introduce a "Do"-interface instead of the above type. But now my code looks a lot uglier:
insteadOf("search", "forest|ground", object : World.InsteadOf.Do {
override fun invoke() {
println("Do something")
}
})
How can I use the simple { } - syntax with the Do-interface?
Here's some clarification.
I'm kind of confused (not news).
The actual Kryo error message seems to be about no-args constructor, however instantly after that it says: "This is an anonymous class, which is not serializable by default in Kryo.".
Here is the full error message:
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)
Here's the InsteadOf-class:
class InsteadOf {
var verbs: Array<String> = arrayOf()
var nouns: Array<String> = arrayOf()
var where: String = ""
var call: (() -> Unit)? = null
}
Upvotes: 2
Views: 744
Reputation: 903
Well, I simply ended up switching to core Java serialization and the problem went away.
Upvotes: 0
Reputation: 3453
It's not completely clear what's wrong with your code. But if you are missing a no-args constructor there are two ways:
no-arg
compiler plugin to specify class that need extra constructor
org.jetbrains.kotlin:kotlin-noarg
A lot of serialisation-related libs force user to have no-arg constructor.' There is a related issue in kryo github.
In case your problem is not related to no-arg
- your question will be a duplicate for this
Upvotes: 0
Reputation: 148159
You can basically accept a () -> Unit
function in insteadOf
and wrap it into a Do
instance in the body:
fun insteadOf(foo: String, bar: String, call: () -> Unit) {
val doInstance = World.InsteadOf.Do(call)
/* use doInstance */
}
The usages will stay the same as in your first example.
Alternatively, provide the Do
interface with a factory function that accepts () -> Unit
and returns a Do
instance.
Upvotes: 1