Ask the Non-Generic Class to Use a Common Argument in the Constructor

I would like to have a non-generic class in kotlin that uses generics in its constructor to specify this parameter. However, I cannot figure out how to do this, and the Java-to-Kotlin converter for Intellij is interrupted.

My java class looks like

public class Test { interface I1 { } interface I2 { } private final I1 mI1; private final I2 mI2; public <T extends I1 & I2> Test(T host) { mI1 = host; mI2 = host; } } 

The output of the converter is as follows.

 class Test(host: T) where T: I1, T: I2 { internal interface I1 internal interface I2 private val mI1: I1 private val mI2: I2 init { mI1 = host mI2 = host } } 

I would like to do this because in Android development it is useful to specify a constructor parameter that looks like <Host extends Context & CustomCallbackInterface>

+6
source share
2 answers

Looking at the Kotlin grammar , it seems that this is not possible at the moment. For primary designers, type parameters denote class type parameters:

 class (used by memberDeclaration, declaration, toplevelObject) : modifiers ("class" | "interface") SimpleName typeParameters? primaryConstructor? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody) ; 

There are no type parameters for secondary constructors:

 secondaryConstructor (used by memberDeclaration) : modifiers "constructor" valueParameters (":" constructorDelegationCall)? block ; 

However, the constructor is just a special function. If we do not use the constructor instead, but a function of our own, we can come up with the following:

 class Test { interface I1 interface I2 private val mI1: I1 private val mI2: I2 internal constructor(host: I1, host2: I2) { mI1 = host mI2 = host2 } companion object { fun <T> create(host: T): Test where T : Test.I1, T : Test.I2 { return Test(host, host) } } } fun <T> test(host: T): Test where T : Test.I1, T : Test.I2 { return Test(host, host) } 

Now we can call Test.create(host) or test(host) to create an instance.

+5
source

By expanding the nhaarman response , you can use operator overloading to make the Test companion object implement the invoke operator :

 class Test { interface I1 interface I2 private val mI1: I1 private val mI2: I2 private constructor(i1: I1, i2: I2) { mI1 = i1 mI2 = i2 } companion object { operator fun <T> invoke(host: T): Test where T : I1, T : I2 { return Test(host, host) } } } 

You can then create the Test object using the call syntax you want:

 Test(object : Test.I1, Test.I2 {}) 
+2
source

All Articles