How to compare classes and interfaces?

11,706

Kotlin reflection doesn't have an API for retrieving information about KClass hierarchy, so the only way to check if one KClass is superclass or subclass of another KClass is to compare corresponding java classes:

interface IB {}
interface IC : IB {}

open class A {}
open class B : A() {}
open class C : B(), IC {}

fun main(args: Array<String>) {
  if (B::class == B::class) { println("B class is equal to B class") }
  if (IB::class == IB::class) { println("IB interface is equal to IB interface") }

  if (A::class.java.isAssignableFrom(B::class.java)) { println("A class is parent of B class") }
  if (A::class.java.isAssignableFrom(C::class.java)) { println("A class is superclass of C class") }

  if (IC::class.java.isAssignableFrom(C::class.java)) { println("C class implements IC interface") }
  if (IB::class.java.isAssignableFrom(IC::class.java)) { println("IC interface implements IB interface") }
}

UPDATE: You can also define two extension functions that will make this kind of checks a bit nicer:

inline fun <reified L : Any, reified R : Any> isSubClassOf(): Boolean {
  return R::class.java.isAssignableFrom(L::class.java)
}

inline fun <reified L : Any, reified R : Any> isSuperClassOf(): Boolean {
  return L::class.java.isAssignableFrom(R::class.java)
}

fun main(args: Array<String>) {
  if (isSubClassOf<B, B>()) { println("B class is equal to B class") }
  if (isSubClassOf<IB, IB>()) { println("IB interface is equal to IB interface") }

  if (isSuperClassOf<A, B>()) { println("A class is parent of B class") }
  if (isSuperClassOf<A, C>()) { println("A class is superclass of C class") }

  if (isSubClassOf<C, IC>()) { println("C class implements IC interface") }
  if (isSubClassOf<IC, IB>()) { println("IC interface implements IB interface") }
}
Share:
11,706
Maxim
Author by

Maxim

Software Developer Linkedin

Updated on June 18, 2022

Comments

  • Maxim
    Maxim almost 2 years

    Can anybody explain me how to compare KClasses and interfaces among themselves? I know how to check if classes or interfaces are equal but I don't understand how to check if A class is a superclass of B class, etc.

    interface IB {}
    interface IC : IB {}
    
    open class A {}
    open class B : A() {}
    open class C : B(), IC {}
    
    fun main(args: Array<String>) {
      if (B::class == B::class) { println("B class is equal to B class") }
      if (IB::class == IB::class) { println("IB interface is equal to IB interface") }
        
      if (A::class ??? B::class) { println("A class is parent of B class") }
      if (A::class ??? C::class) { println("A class is superclass of C class") }
        
      if (C::class ??? IC) { println("C class implements IC interface") }
      if (IC ??? IB) { println("IC interface implements IB interface") }
    }
    
  • voddan
    voddan about 8 years
    wow, I would expect compareTo operator to be overloaded for that
  • Vladimir Mironov
    Vladimir Mironov about 8 years
    @voddan you can not define a compareTo operator for partially ordered sets
  • Maxim
    Maxim about 8 years
    @VladimirMironov I think @voddan mean something like this. As you can see possible to override compareTo and use <, >, <=, >= operators for compare classes (for example such syntax using in Ruby). I hope kotlin.reflect will have something like this in the future.
  • Vladimir Mironov
    Vladimir Mironov about 8 years
    @maxd stdlib will never have such operator because it's just impossible to properly implement compareTo for KClass. Your implementation violates compareTo contract, because it should never throw.
  • voddan
    voddan about 8 years
    @VladimirMironov this contract to never throw out of compareTo exists in Java, but does not in Kotlin (no checked exceptions as a concept). I think the implementation mentioned by @maxd makes sense and violates nothing since it is invisible from Java
  • Nikola Mihajlović
    Nikola Mihajlović about 6 years
    There are extensions: isSuperclassOf isSubclassOf. So there is no need to define your own. Make sure to include kotlin-reflect library though