2016-02-04 16 views
6

Tôi muốn có một lớp không chung chung trong kotlin sử dụng Generics trong hàm khởi tạo của nó để xác định một tham số. Tuy nhiên, tôi không thể tìm ra cách để làm điều này, và bộ chuyển đổi Java-to-Kotlin cho Intellij bị hỏng.Có một lớp Non-Generic có một đối số chung trong hàm tạo

lớp java của tôi trông giống như đầu ra này

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

của chuyển đổi trông như thế này.

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

Tôi muốn làm điều này bởi vì trong phát triển Android nó rất hữu ích để có thể xác định một tham số constructor trông giống như <Host extends Context & CustomCallbackInterface>

Trả lời

5

Nhìn vào Kotlin của grammar, có vẻ như điều này là không thể tại chốc lát. Đối với nhà thầu chính, các thông số loại biểu thị các thông số kiểu lớp:

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

Đối với nhà xây dựng trung học, không có tham số kiểu có thể:

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

Tuy nhiên, một hàm tạo chỉ là một hàm đặc biệt. Nếu chúng ta thay vì không sử dụng các nhà xây dựng, nhưng một chức năng của riêng của chúng tôi, chúng tôi có thể đưa ra như sau:

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

Bây giờ chúng ta có thể gọi Test.create(host) hoặc test(host) để tạo ra một ví dụ.

+1

Đây được gọi là "nhà máy". Sẽ là tốt để giải thích đối tượng đồng hành trong một câu. Ngoài ra chú thích @JvmStatic có thể tốt ở đây nếu họ muốn gọi cho nhà máy như - nếu đó là lớp tĩnh. –

2

Mở rộng trên nhaarman 's answer bạn có thể sử dụng operator overloading để làm Test' s companion object thực hiện 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) 
     } 
    } 
} 

Sau đó, bạn có thể tạo một đối tượng Test sử dụng cú pháp gọi bạn muốn:

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

Các vấn đề với cách tiếp cận này là nó không phải là một nhà xây dựng thực tế từ quan điểm của Java hoặc các ngôn ngữ JVM khác (nếu điều đó quan trọng), cho những tên sẽ là lạ nếu họ thậm chí tìm thấy các chức năng (@JvmStatic sẽ giúp). Và sự phản chiếu cũng sẽ không thấy nó như một nhà xây dựng (một lần nữa, có thể không quan trọng). –

Các vấn đề liên quan