2017-10-22 4 views
6

T 및 일부 메타 데이터의 배열 (또는 목록)이 포함 된 인터페이스가 있습니다. 나는 인터페이스의 간단한 구현을 작성하는 경우Kotlin 제네릭 배열 <T> "Reified 형식 매개 변수로 T를 사용할 수 없습니다. 대신 클래스 사용"으로 표시되지만 은 표시되지 않습니다.

interface DataWithMetadata<T> { 
    val someMetadata: Int 
    fun getData(): Array<T> 
} 

, 나는에 컴파일 오류를 얻을 emptyArray() "구체화 타입 매개 변수로 T를 사용할 수 없습니다 대신 클래스를 사용합니다.." 나는 인터페이스와 목록에 구현 모두를 변경하는 경우

class ArrayWithMetadata<T>(override val someMetadata: Int): DataWithMetadata<T> { 
    private var myData: Array<T> = emptyArray() 

    override fun getData(): Array<T> { 
     return myData 
    } 

    fun addData(moreData: Array<T>) { 
     this.myData += moreData 
    } 
} 

그러나, 나는 더 컴파일시 문제가 없습니다 :

interface DataWithMetadata<T> { 
    val someMetadata: Int 
    fun getData(): List<T> 
} 

class ListWithMetadata<T>(override val someMetadata: Int): DataWithMetadata<T> { 
    private var myData: List<T> = emptyList() 

    override fun getData(): List<T> { 
     return myData 
    } 

    fun addData(moreData: Array<T>) { 
     this.myData += moreData 
    } 
} 

내가 코 틀린 제네릭에 몇 가지 흥미로운 교훈은 내 문제 내부가 의심 . 누구나 컴파일러가 후드에서 수행하는 작업과 어레이가 실패하지만 목록이없는 이유를 알 수 있습니까? 이 컨텍스트에서 Array 구현을 컴파일하는 관용적 인 방법이 있습니까?

보너스 질문 : 내가 Array over List에 도달 한 유일한 이유는 내가 종종 Kotlin 개발자들이 Array를 선호한다는 것입니다. 이 경우인가요? 그렇다면 이유는 무엇입니까?

public inline fun <reified @PureReifiable T> emptyArray(): Array<T> 

reified 유형의 매개 변수는 컴파일시 T의 클래스에 액세스 할 수 있음을 의미 다음 코 틀린의 다음 stdlib (JVM)에서 emptyArray()의 선언을 보면

답변

5

, 우리는 reified 형식 매개 변수를 알 T::class처럼 액세스 할 수 있습니다. Kotlin referencereified 유형 매개 변수에 대한 자세한 내용을 볼 수 있습니다. Array<T>T[]으로 컴파일되기 때문에 컴파일시 유형을 알아야하므로 reified 매개 변수입니다.

: 이제 emptyList()의 구현을 살펴 보자, 지금

fun <T> emptyArray() : Array<T> = Array(0, { throw Exception() }) 

Cannot use T as a reified type parameter. Use a class instead.


: 당신이 reified 키워드없이 emptyArray() 함수를 작성하려고하면 컴파일러 오류가 발생합니다

public fun <T> emptyList(): List<T> = EmptyList 

이 구현에는 매개 변수 T이 전혀 필요하지 않습니다. 내부 객체를 반환하며 그 자체는 List<Nothing>에서 상속받습니다. kotlin 형식 Nothingthrow 키워드의 반환 형식이며 (reference) 값이없는 값입니다. 메서드가 Nothing을 반환하면 is는 해당 위치에서 예외를 throw하는 것과 같습니다. 따라서 EmptyList.get()을 호출 할 때마다 예외가 반환 될 것이므로 컴파일러에서 Nothing을 안전하게 사용할 수 있습니다.


보너스 질문 : 자바와 C++에서 오는

, 나는 배열 것을 사용하는 것이 훨씬 쉽게 할 ArrayList 또는 std::vector에 사용하고있다. 몇 달 동안 kotlin을 사용하고 있으며 소스 코드를 작성할 때 배열과 목록간에 큰 차이가없는 것을 보았습니다.둘 다 비슷한 방식으로 행동하는 유용한 확장 기능이 많습니다. 그러나 Kotlin 컴파일러는 배열과 목록을 매우 다르게 처리합니다. Java 상호 운용성이 Kotlin 팀에게 매우 중요하기 때문입니다. 나는 보통 목록을 사용하는 것을 선호하며, 그것은 내가 귀하의 경우에도 권하고 싶습니다.

2

문제는 알려진해야하는 Array의 일반 요소 형식이 선언에서 볼 수 있듯이, 여기에 reified 형식 매개 변수로 표시됩니다 시간를 컴파일하는 것이된다

public inline fun <reified @PureReifiable T> emptyArray(): Array<T> 

그것은 단지이다 Array<String> 또는 Array<Int> 같은 구체적인 배열을 만들 수 있지만 유형 Array<T>의. 이 answer에서

, 당신은 몇 가지 해결 방법을 찾을 수 있습니다. 당신이 적당한 길을 찾을 수 있기를 바랍니다.