Contents

Subtyping

Subtyping (<:)

Subtyping Test Code

  • Subtyping (subtype <: supertype) is a reflexive and transitive relation on two types, include:

    • identity
    • subclassing
    • interface extension
    • interface implementation
  • Subtyping enables upcasting.

  • To examine subtyping relation of all the above cases

    SUPERTYPE.class.isAssignableFrom(SUBTYPE.class)

Identity

Every type is a subtype of itself, by reflexivity of subtyping.

  • To examine identity relation

    A.class == B.class

    NOTE: Within a given class loader, a class (by name) has exactly one Class object at runtime.

    ClassLoader loader1 = ...;
    ClassLoader loader2 = ...;
    
    Class<?> a = loader1.loadClass("mypkg.MyClass");
    Class<?> b = loader2.loadClass("mypkg.MyClass");
    
    assertFalse(a == b);        // FALSE

Subclassing

class A {}
class B extends A {}
class C extends B {}

B is a subtype of A by direct class inheritance.

C is a subtype of A by indirect class inheritance.

Subclassing is about two classes not interfaces.

  • To examine direct class inheritance

    A.class == B.class.getSuperclass()
  • To examine direct and indirect class inheritance

    private boolean isSubclass(Class<?> possibleSub, Class<?> possibleSuper) {
      if (possibleSub == null || possibleSuper == null
                              || possibleSub == possibleSuper)
        return false;
      Class<?> clazz = possibleSub;
      for (; clazz != null && clazz != possibleSuper;
             clazz = clazz.getSuperclass()) ;
      if (clazz != null) return true;
      return false;
    }
    
    isSubclass(C.class, A.class)

NOTE: Object is the root of the class hierarchy. It has no superclass and is not a subclass of any class. But it is its own subtype, by reflexivity of subtyping.

Object.class.getSuperclass() == null

Interface extension

interface Intf {}
interface IntfSub extends Intf {}

IntfSub is a subtype of Intf by interface extension.

NOTE: Every interface is a subtype of Object, but not a subclass of Object. Interfaces have no superclass.

Interface implementation

interface Intf {}
class ClassA implements Intf {}

ClassA is a subtype of Intf by implementation.

isAssignableFrom() and isInstance()

if (Super.class.isAssignableFrom(obj.getClass())) {
 assert obj instanceof Super;  // compile time check: Super is known
}

Class<?> c;
if (c.isAssignableFrom(obj.getClass()) {
 assert c.isInstance(obj);     // runtime check: type of c is dynamic
}

private void assert_isInstance_isAssignableFrom(Class<?> c, Object o) {
  assertTrue(c.isAssignableFrom(o.getClass()));
  assertTrue(c.isInstance(o));
}