Hi everyone! Lets say I have the following struct...
# getting-started
g
Hi everyone! Lets say I have the following structure:
Copy code
class Test {
    val firstValue: String
    val secondValue: Long
}

class TestWrapper {
    val firstValue: Wrapper<String>
    val secondValue: Wrapper<Long>
}
Would it be possible somehow to create a common interface/class for these two classes? For example, if it would be possible, using union types:
Copy code
interface InterfaceTest<T : Wrapper<T>, T>
But given that is not possible, is it some other way Kotlin can handle this?
e
Kotlin (like Java) has first-order generics only, no higher-order types, so not really.
j
How would you use that common interface?
g
The goal is to create the
Test
class based on
TestWrapper
via some reflections. And the purpose for the interface would just be for safety. That is that the value the wrapper wraps is the same type as the actual value.
Copy code
class Test {
    val firstValue: String
    val secondValue: Long
}

class TestWrapper {
    val firstValue: Wrapper<Long>
    val secondValue: Wrapper<Long>
}
Here the
TestWrapper#firstValue
wrapps a
Long
but the
Test#firstValue
is of type
String
j
But if the
Test
class is generated from
TestWrapper
via reflection, why would the type not match?
g
Hm... Today it is generated based on defined values, so the reflection is just setting the values, because in the end it works as a response DTO.
j
Oh ok I think I misunderstood your previous statement. You're not creating the
Test
class from the
TestWrapper
class, you're creating
Test
instances via reflection from instances of the
TestWrapper
class, right?
g
Oh, right. Yeah. Sorry. So I first create a
Test
instance (with just one required value), and then I use reflection to set all the values matched (by name and type) via reflection for the other values in the
Test
instance
j
I see. And so your goal would be to make the function that does this reflection generic, and have a way to enforce at compile time that the type of the wrapper class is sort of "compatible" with the type of the DTO class, right? If that's the case, I don't think this is possible, unfortunately.
g
Yepp, thats it!
e
I should correct my terminology: they're typically named higher-kinded types
👍 1
j
You could also consider using code generation that generates one of the classes from the other, as well as methods that map wrappers to the corresponding DTOs
e
analogous to higher-order functions, but on types
g
Oh... Right. Code generation would eliminate the code duplication, as well as ensure compatibility. That sounds like the way to go. Thank you!
e
yes I agree there will not be a safe way to ensure this type mapping within the language. custom codegen can enforce your own requirements such as this.
j
the only solution I can think of is to create common interfaces for your values, you could do something like that :
Copy code
interface ValueProvider<T> {
  fun getValue(): T
}

class Value: ValueProvider {}
class ValueWrapper: ValueProvider {}

class Test {
    val firstValue: Value<String>
    val secondValue: Value<Long>
}

class TestWrapper {
    val firstValue: ValueWrapper<String>
    val secondValue: ValueWrapper<Long>
}
Then you can create a common interface for your
Test
and
TestWrapper
classes :
Copy code
interface InterfaceTest {
    val firstValue: ValueProvider<String>
    val secondValue: ValueProvider<Long>
}
j
Yes, but I guess the initial idea was that the DTO's properties were not wrapped in any custom type like this, so creating another wrapper for this purpose defeats the purpose of the conversion (at least from what I understood of the @Gustav Elmgren's intention)
j
ah yes, it may not be a good option
g
That is correct, i kinda defeats the purpose as you said @Joffrey.
j
It's worth mentioning as an option though, it might be ok for other people finding this thread 😉
m
I still think Kotlin needs union types. Sometimes on inferencing level we'll see
<Type1 | Type2>
and I'm kinda surprised that functionality just plain doesn't exist on declaring level.