https://kotlinlang.org logo
Title
j

jeggy

04/10/2019, 1:45 PM
abstract class A {
    abstract val value: String
    abstract fun <T: A> test(): T
}

data class B(
    override val value: String,
    val value2: String
): A() {
    override fun test() 
        = this.copy(value = "HelloWorld")
}
How can I achieve something like this?
d

diesieben07

04/10/2019, 1:47 PM
abstract class A<T : A<T>> {
    abstract val value: String
    abstract fun test(): T
}

data class B(
    override val value: String,
    val value2: String
): A<B>() {
    override fun test()
            = this.copy(value = "HelloWorld")
}
👆 1
s

Shawn

04/10/2019, 1:48 PM
Recursive templates are about the only way you can approximate self types on the JVM unfortunately
j

jeggy

04/10/2019, 1:51 PM
I tried this way, this results in getting A back. I have some other function that takes B in, so I want to be able to call
funTakesB(b.test())
, but this fails as b.test() returns
A<*>
instead of
B
r

Ruckus

04/10/2019, 1:52 PM
What is
b
?
j

jeggy

04/10/2019, 1:52 PM
an instance of
B
I'll just cast it, I know it will always be the right one
d

diesieben07

04/10/2019, 1:54 PM
I can't reproduce what you're reporting:
abstract class A<T : A<T>> {
    abstract val value: String
    abstract fun test(): T
}

data class B(
    override val value: String,
    val value2: String
): A<B>() {
    override fun test()
            = this.copy(value = "HelloWorld")
}

fun funTakesB(b: B) {

}

fun foo() {
    val b = B("foo", "bar")
    funTakesB(b.test())
}
This works fine
r

Ruckus

04/10/2019, 1:54 PM
If it's an instance of
B
it will work fine. Are you sure it's not inferred as an instance of
A
?
j

jeggy

04/10/2019, 1:55 PM
probably, I will write a better example. Wait a min
I don't find any easy way of showing the use case for this, as I'm working in a bigger project. But this is it: https://pl.kotl.in/B1SSwdiF4
I just used
as T
there, which works fine. Was just wondering if I somehow can get rid of it
s

streetsofboston

04/10/2019, 2:04 PM
abstract class Service<T: A<T>> {
    abstract fun extra(any: T)
    fun someWork(any: T) {
        extra(any.test())
    }
}
j

jeggy

04/10/2019, 2:05 PM
Ah, sorry. That was obvious xD
Thanks for the help
👍 1