2017-03-11 1 views
6

나는 현재 라이브러리의 DSL을 쓰고 있어요 및 I는 다음과 같이 구체화 형 매개 변수를 사용하여 형식 메타 데이터를 제공하고 싶습니다 :Kotlin의 인스턴스 필드에 구체화 된 유형 데이터를 저장하려면 어떻게해야합니까?

val config = Config.create() 
      .consumerFor<MyType>{ 
       // consume 
      } 

내 문제는 내가 단지 inline 기능에 reified 키워드를 사용할 수 있고 inline 기능에 나는이 같은 인스턴스 필드를 사용할 수 없습니다

inline fun <reified T> consumerFor(consumer: (T) -> Unit) { 
     consumers.put(T::class.java, consumer) 
     return this 
    } 

를 내가 오류 얻을 수 있기 때문에 :

Public-API inline function cannot access non-public-API 'private final val consumers...

가장 유용한 곳에 구체화 된 유형 매개 변수를 사용할 수없는 것 같습니다. 이 문제를 해결할 수있는 방법이 있습니까? 클래스 외부 호출 사이트에 인라인 때 용도는 (JVM에, 클래스의 private 구성원이 외부에서 액세스 할 수 없습니다) 잘못된 액세스 수준이있을 것이다, 때문에

답변

6

공공 inline 기능은 직접 private 선언을 사용할 수 없습니다.

당신이 할 수있는 일은 Kotlin에서 the internal visibility을 사용하는 것입니다. JVM에서이 가시성 수정자를 가진 멤버는 이름이 맹 글링 된 공개 멤버로 컴파일되므로 Java에서 쉽게 볼 수는 있지만 쉽게 호출 할 수는 없습니다. Kotlin 컴파일러는 적어도 Kotlin 코드에서 사용법을 제어합니다.

public inline fun 내에서 internal 멤버에 액세스이 질문에 볼 수있는 몇 가지 방법이 있습니다, 특정 경우 (link)

을 내가 @PublishedApi와 함께 그 일을 선호하는 것 :

private val consumers = mutableMapOf<Class<*>, Any>() 

@PublishedApi 
internal fun <T> putConsumer(clazz: Class<out T>, consumer: (T) -> Unit) { 
    consumers.put(clazz, consumer) 
} 

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit): C { 
    putConsumer(T::class.java, consumer) 
    return this 
} 

또는, consumers@PublishedApi으로 노출시키지 않으려면 다음과 같이하십시오.

@PublishedApi 
internal val consumers = mutableMapOf<Class<*>, Any>() 

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit): C { 
    consumers.put(T::class.java, consumer) 
    return this 
} 
+0

괜찮습니다. 고맙습니다. 이것은 최종 필드가있는 구성 클래스 일 뿐이므로 신경 쓰지 않아도됩니다. –

1

reified 유형 매개 변수가 필요한 경우 해당 Java 클래스를 반영하는 것이기 때문에 추가 Class<T> 매개 변수로 비 인라인 오버로드로 관리 할 수 ​​있습니다.

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit) = 
    consumerFor(T::class.java, consumer) 

fun <T> consumerFor(key: Class<T>, consumer: (T) -> Unit) = apply { 
    consumers.put(key, consumer) 
} 

이렇게하면 consumers 속성이 효과적으로 게시되지 않습니다. 보너스 포인트는 Java에서도 비 인라인 오버로드를 호출 할 수 있다는 것입니다.