2016-02-04 19 views
6

Chciałbym mieć klasę nietypową w kotlinach, która używa generycznych w swoim konstruktorze w celu określenia tego parametru. Jednak nie mogę wymyślić, jak to zrobić, i konwerter Java-to-Kotlin dla przerw Intelli.Czy klasa Non-Generic przyjmuje ogólny argument w konstruktorze

Moja klasa java wygląda wyjście tego

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; 
    } 
} 

konwertera wygląda tak.

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 
    } 
} 

Chciałbym to zrobić, ponieważ w rozwoju Android jest użyteczne, aby móc określić parametr konstruktora, który wygląda jak <Host extends Context & CustomCallbackInterface>

Odpowiedz

5

Patrząc Kotlin na grammar, wydaje się, że nie jest to możliwe u za chwilę. Dla konstruktorów pierwotnych parametrów typ oznaczenia parametrów typu klasy:

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

dla konstruktorów wtórnych, nie ma parametrów, typu możliwe:

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

Jednak Konstruktor jest tylko specjalną funkcją. Gdybyśmy zamiast nie użyć konstruktora, ale funkcję własną rękę, możemy wymyślić, co następuje:

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) 
} 

Teraz możemy nazwać Test.create(host) lub test(host) utworzyć instancję.

+1

To się nazywa "fabryka". Byłoby dobrze wytłumaczyć obiekt towarzyszący w jednym zdaniu. Również adnotacja @JvmStatic, która może być dobra tutaj, jeśli chcą wywołać fabrykę jako - jeśli jest to klasa statyczna. –

2

Rozszerzając nhaarman 's answer można użyć operator overloading aby Test' s companion object wdrożenia invokeoperator:

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) 
     } 
    } 
} 

Następnie można utworzyć Test obiektu przy użyciu składni wywołania chcesz:

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

Kłopot z tym podejściem polega na tym, że nie jest on rzeczywistym konstruktorem z punktu widzenia Javy lub innych języków JVM (jeśli to ma znaczenie), dla których nazwa będzie dziwna, nawet jeśli znajdą funkcję (pomoże @JvmStatic). I refleksja także nie zobaczy go jako konstruktora (znowu, może nie mieć znaczenia). –

Powiązane problemy