2016-09-21 4 views
5

Ich versuche, wenn ein Typ mit einem zu einem anderen Typ entspricht zu überprüfen, ob Ausdruck wie folgt:Kotlin-Klassenliterale mit leerer linker Seite werden noch nicht unterstützt?

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

Das gibt mir die Fehlerklasse Literale mit leerer linker Seite werden noch nicht unterstützt. Kann jemand diesen Fehler erklären und/oder mir sagen, wie ich diesen Check machen soll?

edit (Erläuterung): Ich kann keine Gleichheitsprüfung durchführen, weil ich wissen muss, ob die Klasse auf der linken Seite entweder der Klasse auf der rechten Seite entspricht oder eine Unterklasse davon ist. Also, wenn eine Instanz der Klasse auf der linken Seite sicher in die Klasse auf der rechten Seite umgewandelt werden kann.

Grundsätzlich muss ich das Äquivalent von:

if ("A string" is Any) 

Aber ohne eine String-Instanz mit, String gerade hier ein Beispiel verwendet wird.

+0

Mein Kollege einen anderen SO Post gefunden, die sagt Kotlin hat Es gibt keine Möglichkeit, dies zu tun, und die einzige Möglichkeit besteht darin, Java-Reflektion zu verwenden (vorausgesetzt, Sie richten sich an JVM). http://stackoverflow.com/questions/35851719/how-to-compare-classes-and-interfaces/35852445#35852445 – zjuhasz

Antwort

3

Ihre Fehlermeldung, dass das is Check erwartet Klassenname und kein Verweis auf eine KClass auf der rechten Seite. Die Nachricht selbst könnte ein wenig unklar sein. Aber das gleiche gilt in Java, Sie würden nicht instanceOf Operator verwenden, sondern stattdessen isAssignableFrom aufrufen.

Hilfe zur Lösung des Problems haben Sie Beispiele, die in Github zu finden sind ...

In den Klutter library sind Beispiele für viele Kombinationen von instanceOf Stil zwischen Class, Prüfen KClass, Type und KType als gut als Primitive. Sie können Ideen von dort kopieren. Es gibt viele Kombinationen, die Sie auf lange Sicht abdecken möchten.

Hier ist eine Stichprobe von a big mix of extensions für die Überprüfung, ob ein Typ von den anderen zuweisbar ist. Ein paar Beispiele sind:

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 

Siehe linked source for all permutations.

Und Sie werden diese erasedType() extension durch die obigen Proben müssen - was einer Class von einem Type zurück geht (nach Typ Löschung):

@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

Ich denke, es wäre nicht klar, wenn Kotlin den is-Operator zwischen einer KClass und einer anderen KClass anders verwendet, als zwischen einer Instanz und einem Typ, weshalb das, was ich zu tun versuchte, nicht funktioniert. Jedenfalls habe ich diese kleine Infix-Funktion gemacht, um die Funktionalität zu imitieren. Es funktioniert natürlich nur mit dem JVM-Ziel, da es Java-Reflektion verwendet. Dies geht von der answer given in this SO post.

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

Dies ermöglicht es Ihnen, genau das zu tun, was ich versuche zu tun, sondern mit der Dose Funktion anstelle der is Operator wie folgt: a

if(String:class can Any::class) 
Verwandte Themen