I'm trying to get a class similar to this (contrived) example to compile:
class Foo<T> {
val value: T
val condition: Boolean
fun <R> transform(func: () -> R): R {
return if (condition) {
func()
} else {
// Type mismatch: required: R, found: T
value
}
}
}
The transform
method can return either value
or the result of func()
, so T
should be assignable to R
. Is there a way to express this in Kotlin?
I tried using where T : R
, but the compiler doesn't understand that T
should refer to the class's T
. An extension function could work, but I want to avoid that because it complicates Java interoperability.
CodePudding user response:
You can try this , it works. You need to pass two type params while initializing.
class Foo<T:R,R> constructor(val value: T,val condition: Boolean) {
fun transform(func: () -> R): R {
return if (condition) {
func()
} else {
value
}
}
}
Example:
var s = Foo<String,CharSequence>("12",false).transform {
"as"
}
You pass "12" as string . Transform return "as" value as CharSequence .
Update: As far as I know, only using extension function might be solve your requirement.
Here is the extension function solution.
class Foo<T> constructor(val value: T,val condition: Boolean){}
fun <T:R,R> Foo<T>.transform(func: () -> R):R{
return if (condition) {
func()
} else {
value
}
}
Example of using extension function solution.
fun main() {
var s1 = Foo(setOf("Hello"),false).transform<Set<String>,Iterable<String>> {
setOf("World")
}
var s2 = Foo(listOf("Hello"),false).transform<List<String>,Iterable<String>> {
listOf("World")
}
}
CodePudding user response:
You just use the type parameter from the class directly. Your method doesn't need to introduce another type parameter:
class Foo<T> {
val value: T
val condition: Boolean
fun transform(func: () -> T): T {
return if (condition) {
func()
} else {
value
}
}
}