Search code examples
javasubtype

What is the difference between "Java subtype" and "true subtype"


I've just now encountered the phrases "java subtype" and "true subtype". It was given in a question in a way that makes clear that they are not the same. But I couldn't find an explanation on what is the difference between the two.

Can someone please explain the differences between "java subtype" and "true subtype"?


Solution

  • A java subtype is any class that extends another class (or even implements an interface). A true subtype is not something language specific:

    A true subtype can always be substituted for the supertype. "Any property guaranteed by supertype must be guaranteed by subtype (true subtyping)"

    http://www.cs.washington.edu/education/courses/cse331/10au/lectures/subtypingexamples.pdf

    The link contains a very enlightning example. Let's say you have a class Point2D that stores values x and y. You could now create a subtype Point3D and add a value z. If you don't override any methods and take care with your equals and hashcode methods you could substitute a Point3D instance at any time for a Point2D instance.

    This is a simple example of course. One could argue why not have only Point3D. Maybe the classes both offer some methods that can - by dividing up into to classes - be better recognized as belonging to the 2D or 3D realm. In this case it would probably be purely a design decision.

    class Point2D {
       int x;
       int y;
    }
    
    //true subtype
    class Point3D extends Point2D {
       int z;
    }
    

    A more complex example might arise if you take a Person class and then have two subtypes: Employee and Customer. Both Employee and Customer offer all the same fields and methods as a Person.

    class Person {
       String name;
       Date birthday;
    
       @Override
       public boolean equals(Object o){
           //simplified equals implementation, this does not fulfill equals contract!
           return name.equals(((Person)o).name);
       }
    }
    
    //true subtype, same behaviour
    class Employee extends Person {
       long departmentId;
    }
    
    //not a true subtype, different behaviour -> equals
    class Customer extends Person {
       long customerId;
       Date lastContact;
       String city;
    
       public boolean equals(Object o){
           //simplified equals implementation, this does not fulfill equals contract!
           return customerId.equals(((Customer)o).customerId);
       }
    } 
    

    In this example Employee would be a true subtype of Person. However Customer is not a true subtype because the equals implementation differs (and presumably hashCode() as well) and it would not behave the same and could probably not be substituted for a Person object at all times.