Proposal: Generics new constraint ``` data class C...
# language-proposals
s
Proposal: Generics new constraint
Copy code
data class CPosition(var x: Int, var y: Int)

fun main(args: Array<String>)
{
    addComponent<CPosition>().apply {
        x = 5
        y = 5
    }
}


fun <T : new> addComponent(): T
{
    // create an instance of T
    val c = T()
    
    // do stuff with c
    
    return c
}
m
Can't you just pass the constructor as an argument?
Copy code
fun <T> addComponent(createT: () -> T): T {
    val c = createT()
    // ...
    return c
}

addComponent(::SomeClass)
👍 1
s
yes but it feels "hacky"
1
k
What is the actual use case? For this example you could just pass an actual instance to
addComponent
.
s
the use case is actually to not have to care about creating an actual instance before 😛
k
Is it literally
addComponent<CPosition>()
vs
addComponent(CPosition())
?
s
no, so i can implement a type safe object pooling then, user should not care about allocating components
o
It’s a feature request, not a proposal. Proposal should at least give some idea about how it would be implemented, and how it interacts with other features.
k
Just to be sure, have you measured if object pooling really helps performance in your case?
o
When you need object pooling, it is indeed hard to achieve. But just
new
constraint doesn’t really help, because you’ll need to somehow return objects to the pool.
a
Even with such a feature, I would prefer Marius's solution using a higher order function. Makes it more flexible, and less magic. (What happens to constructor params?)
t
Yeah just use higher order functions. That's just more flexible, as you can also require constructors to have parameters
t
Make your type parameter reified and call constructor through reflection is what you want
k
That's another can of worms, no compile time safety any more.
t
Something similar can be achieved with the typeclasses proposal. With that you can add a typeclass parameter with a factory method. You'd still need to define the factory (typeclass implementation) somewhere, but the call site will look like what you wanted.
d
You could also achieve this with companion objects, similar to how Kotlin/Native does
memScope.allocArray<T>(block: T.() -> Unit)
. Although you'd have to do this for every "component".
It's sadly an intrinsic.
b
In Swift, I solved this by creating a
protocol InitializablyWithZeroArguments
, which only requires that it has n initializer that takes zero arguments. Then I just use protocol `extension`s to make lots of mine and stdlib types conform to it. Unfortunately, Kotlin seems to have no interest in making `interface`s specify a constructor. Nor does Kotlin seem to want late-declared conformance to be a thing. 😞