Hi! Let's say I have a sealed class WriteOperation...
# announcements
g
Hi! Let's say I have a sealed class WriteOperation, with some data classes as children and I want to convert them to corresponding WriteModel classes of mongodb or sql query templates for relational db. So my code for now looks like this:
Copy code
sealed class WriteOperation {
  data class Insert(...some props): WriteOperation()
  data class Delete(...some props): WriteOperation()
  data class Replace... and so on
}
// And then in mongo-related package I do:
fun WriteOperation.toMongoModel(): WriteModel = when (this) {
  is WriteOperation.Insert -> InsertOneModel(...initialization)
  is WriteOperation.Delete -> DeleteOneOperation(...initialization)
  is WriteOperation.Replace -> ...
  ... and also around 12 other conditions
}
// Same thing happens with SQL:
fun WriteOperation.toSqlQuery(): SQLQuery = when (this) {
  ...long and painful list
}
Is there any way of replacing those long when expressions with some kind of inheritance, extension or composition without referencing Mongo or SQL implementation in sealed classes?
y
You can maybe define a map linking each data class with the corresponding SQLQuery and WriteModel?
g
It's not really different, except that you loose all that useful messages from compiler about missing branches, which could prevent a lot of runtime errors. The main reason why it's so problematic is that extension functions are not overloaded. What I mean is:
Copy code
fun WriteOperation.toMongoModel() = TODO("I gonna throw")
fun WriteOperation.Insert.toMongoModel() = InsertOneModel(...)
fun doSomeCalc(op: WriteOperation) = op.toMongoModel()
doSomeCalc(WriteOperation.Insert(...))
Will always throw an exception, and it makes sense if you think of it.
c
Excuse me but could you select all your code text and then click on “Code Block” inside of the “Formatting” menu? you can also use command+option+shift+c
g
Oh, sorry about that, fixed it)
🙃 1
I think I found the answer. Sadly you can not go without explicitly mapping
WriteOperation
to target type, since actual type (Insert, Delete, etc.) is only known at runtime, and any kind of extension will always reference base class. I was also thinking about adding some generic mapping method to sealed class itself but it useless as well, because you'll need to know in what type such mapping should result at compile time... and you can not override it in your specific DB package anyway. So, good old
when
expressions I guess 🙂