Proposal: `This` type for generics (Can kotlin interface detects, on which class is attached to, on its own?)

I have generic interface…

interface Parent<T> {
    fun function(entity: T): Int
}

And when I implement functionality with some child class…

class Other : Parent<Other> {
    override fun function(entity: Other): Int {
        return 42
    }
}

I’m bothered with the fact that I have to pass the same class type while implementing the interface… I would really like for the interface to be able to detect on which class is attached on its own without me providing the same type again…

I would like to have something like python has: PEP 673: Self type

interface Parent<This> {
    fun function(entity: This): Int
}

// Interface parameter argument is infered from class type on which interface is used...
class Other : Parent { // <--- so you don't need to provide the same type!
    override fun function(entity: Other): Int {
        return 42
    }
}
3 Likes

Let me see if I’m following.

You have a generic base type. You want to create subtypes that extend this generic without having to write the type parameters when that info can be inferred. You want the type param to be inferred like how it’s done when calling a generic function or declaring a variable. Is that right?

I’d say that’s a decent request but I’d offer this argument against it: Inferring types can cause your code to become less clear and adds the risk for accidental change.

In the case of inferring function calls and declaring variables, the type is still explicitly written out somewhere close by. This is also true in your example since Other is explicitly written on the function. For larger examples, I think it would become a problem.

For the risk of making hard-to-detect changes: Generic types can use their generics in many different places. They can use them as function returns, property types, function parameters, receivers, inner classes, and lambda types in any of those places. All it takes is a few simple uses while trying to infer a generic before you risk returning Number or Any? without knowing.

I’d suspect this feature may be useful in a select few use cases. Maybe someone can come up with an IRL example? Once there’s more than one use of a generic, I’d expect a warning along the lines of “Generic should be explicitly declared”.

1 Like

Yes I think you understand correctly what is my goal…

Let me explain my IRL example…

I have domain entities that must have all implemented same_as function…
And I have in my server application with more than 30 types of entities. The interface will always have parameter type of the class type on which will be attached to and it would be really nice that you could tell the interface that information…

My proposal would be that you could add something like Python did PEP 673: Self type

interface Entity<This> {
    fun same_as(entity: This): Boolean
}

And since interface knows that This means the class type on thich interface is attached to… You could then write interface implementations without providing explicit type because This would always means in the context of this class where interface is used…


data class Person(
    val username: String,
    val age: Int
) : Entity {  // <--- Interface type argument is This class (Person)
    override fun same_as(entity: Person): Boolean {

        return this.username == entity.username

    }
}

data class Company(
    val name: String,
    val address: String
) : Entity {  // <--- Interface type argument is This class (Company)
    override fun same_as(entity: Company): Boolean {

        return this.name == entity.name

    }
}

Ah! Gotcha. Yeah, self-types might be a nice feature.

There’s some existing discussion on Self types. Here’s an older article about emulating self types

Here’s an issue in YouTrack for self types. On that issue is links to other related issues and discussions.

2 Likes

I love you! I will join cho cho train for development of self types.

2 Likes