2016-09-21 13 views
5

Tôi cố gắng để kiểm tra xem một loại phù hợp với một loại khác với nếu biểu hiện như vậy:Các chữ cái lớp Kotlin có mặt bên trái trống không được hỗ trợ?

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

này mang lại cho tôi những literals lớp lỗi với phía bên tay trái có sản phẩm nào chưa được hỗ trợ. Bất cứ ai có thể xây dựng trên lỗi đó và/hoặc cho tôi biết làm thế nào tôi nên làm kiểm tra này?

chỉnh sửa (làm rõ): Tôi không thể thực hiện kiểm tra bình đẳng vì tôi cần biết liệu lớp ở bên trái có khớp với lớp ở bên phải hay là lớp con của nó. Vì vậy, nếu một thể hiện của lớp ở bên trái có thể được đúc an toàn đến lớp ở bên phải.

Về cơ bản tôi cần tương đương với:

if ("A string" is Any) 

Nhưng mà không phải một trường hợp String, String chỉ được sử dụng một ví dụ ở đây.

+0

Đồng nghiệp của tôi tìm thấy một SO bài mà nói Kotlin có không có cách nào để làm điều này và cách duy nhất là sử dụng sự phản chiếu Java (giả sử bạn đang nhắm mục tiêu JVM). http://stackoverflow.com/questions/35851719/how-to-compare-classes-and-interfaces/35852445#35852445 – zjuhasz

Trả lời

3

thông báo lỗi của bạn được rằng việc kiểm tra is hy vọng một tên lớp và không phải là tham chiếu đến KClass ở bên phải. Bản thân thông điệp có thể hơi không rõ ràng. Nhưng điều tương tự cũng áp dụng trong Java, bạn sẽ không sử dụng toán tử instanceOf mà thay vào đó, hãy gọi isAssignableFrom.

Để được trợ giúp vào việc giải quyết vấn đề, bạn có ví dụ có thể được tìm thấy trong Github ...

Trong Klutter library là ví dụ về rất nhiều sự kết hợp của phong cách instanceof kiểm tra giữa Class, KClass, TypeKType như cũng như nguyên thủy. Bạn có thể sao chép ý tưởng từ đó. Có nhiều kết hợp mà bạn có thể muốn có trong thời gian dài.

Đây là mẫu lấy mẫu a big mix of extensions để kiểm tra xem một loại có thể gán cho loại kia hay không. Một vài ví dụ là:

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 

Xem linked source for all permutations.

Và bạn sẽ cần erasedType() extension này được sử dụng bởi các mẫu trên - mà đi từ một Type trở lại một Class (sau khi loại chô bôi):

@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

Tôi đoán nó sẽ không rõ ràng nếu Kotlin sử dụng toán tử khác nhau giữa một KClass và một KClass khác như nó giữa một thể hiện và một loại đó là lý do tại sao những gì tôi đang cố gắng không hoạt động. Dù sao tôi đã thực hiện chức năng này ít infix để bắt chước các chức năng. Tuy nhiên, nó chỉ hoạt động với mục tiêu JVM của khóa học vì nó sử dụng sự phản chiếu Java. Điều này đang tắt của số answer given in this SO post.

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

này sẽ cho phép bạn thực hiện chính xác những gì tôi đã cố gắng làm nhưng với sự can chức năng thay vì là nhà điều hành như sau:

if(String:class can Any::class) 
Các vấn đề liên quan