2016-09-21 2 views
5

Я пытаюсь проверить, если тип соответствует другому типу с выражением, если так:Литералы класса Kotlin с пустой левой стороной еще не поддерживаются?

if (String::class is Any::class) 

Это дает мне класс ошибок литералы с пустой левой стороны пока не поддерживаются. Может ли кто-нибудь уточнить эту ошибку и/или рассказать мне, как я должен делать эту проверку?

Редактировать (уточнять): Я не могу выполнить проверку равенства, потому что мне нужно знать, соответствует ли класс слева или соответствует классу справа или является его подклассом. Поэтому, если экземпляр класса слева можно безопасно применить к классу справа.

В принципе мне нужно эквивалент:

if ("A string" is Any) 

Но, не имея экземпляр String, String просто используется пример.

+0

Мой коллега нашел другую SO пост, который говорит, что Котлин имеет нет способа сделать это, и единственный способ - использовать отражение Java (при условии, что вы нацеливаете JVM). http://stackoverflow.com/questions/35851719/how-to-compare-classes-and-interfaces/35852445#35852445 – zjuhasz

ответ

3

Ваше сообщение об ошибке, что is проверка ожидает имя класса, а не ссылку на KClass справа. Само сообщение может быть немного неясным. Но то же самое относится и к Java, вы не использовали бы оператора instanceOf, а вместо этого вызывали бы isAssignableFrom.

Для помощи в решении этой проблемы, у вас есть примеры, которые можно найти в Github ...

В Klutter library примеры много комбинаций InstanceOf стиля проверки между Class, KClass, Type и KType как а также примитивы. Вы можете копировать идеи оттуда. Есть много комбинаций, которые вы, возможно, захотите охватить в долгосрочной перспективе.

Вот выборка a big mix of extensions для проверки того, можно ли присвоить один тип от другого. Несколько примеров:

fun <T : Any, O : Any> KClass<T>.isAssignableFrom(other: KClass<O>): Boolean { 
    if (this.java == other.java) return true 
    return this.java.isAssignableFrom(other.java) 
} 

fun <T : Any> KClass<T>.isAssignableFrom(other: Class<*>): Boolean { 
    if (this.java == other) return true 
    return this.java.isAssignableFrom(other) 
} 

fun KClass<*>.isAssignableFromOrSamePrimitive(other: KType): Boolean { 
    return (this.java as Type).isAssignableFromOrSamePrimitive(other.javaType) 
} 

fun KClass<*>.isAssignableFromOrSamePrimitive(other: Type): Boolean { 
    return (this.java as Type).isAssignableFromOrSamePrimitive(other) 
} 

fun Type.isAssignableFromOrSamePrimitive(other: Type): Boolean { 
    if (this == other) return true 
    if (this is Class<*>) { 
     if (other is Class<*>) { 
      return this == other.kotlin.javaObjectType || this == other.kotlin.javaPrimitiveType || 
        this.isAssignableFrom(other) 
     } 
     return this.isAssignableFrom(other.erasedType()) 
    } 
    return this.erasedType().isAssignableFrom(other.erasedType()) 
} 

// ... and so on for every permutation of types 

См. linked source for all permutations.

И вы будете нуждаться в этом erasedType() extension, используемый в примерах выше - что идет от Type обратно Class (после типа стирания) в:

@Suppress("UNCHECKED_CAST") fun Type.erasedType(): Class<Any> { 
    return when (this) { 
     is Class<*> -> this as Class<Any> 
     is ParameterizedType -> this.getRawType().erasedType() 
     is GenericArrayType -> { 
      // getting the array type is a bit trickier 
      val elementType = this.getGenericComponentType().erasedType() 
      val testArray = java.lang.reflect.Array.newInstance(elementType, 0) 
      testArray.javaClass 
     } 
     is TypeVariable<*> -> { 
      // not sure yet 
      throw IllegalStateException("Not sure what to do here yet") 
     } 
     is WildcardType -> { 
      this.getUpperBounds()[0].erasedType() 
     } 
     else -> throw IllegalStateException("Should not get here.") 
    } 
} 
4

Я думаю, будет неясно, использовал ли Kotlin оператор is по-разному между KClass и другим KClass, как это происходит между экземпляром и типом, поэтому то, что я пытаюсь сделать, не работает. В любом случае я сделал эту маленькую функцию infix, чтобы имитировать функциональность. Однако он работает только с целью JVM, так как использует Java-отражение. Это происходит от answer given in this SO post.

infix fun <T : Any, C : Any> KClass<T>.can(comparate: KClass<C>) = 
    comparate.java.isAssignableFrom(this.java) 

Это позволит вам делать то, что я пытался сделать, но с функцией может вместо является оператор так:

if(String:class can Any::class) 
Смежные вопросы