If you read yesterday’s post, you should remember that in order to cast form one type to another the compiler must know the relationship between the types.
In java, there are two main types of relationship between the types:
- Interface relationship
- Class relationship
These are called “Inheritace”, which is an Object Oriented Programming term referring to the fact that some types are based in other types, which can be exploited nicely in practical situations.
Interface relationship is either from interface to interface or from interface to class. Now, I need to explain what an interface is. Remember what a class is? A blueprint of operations and data? Interfaces are blueprints of blueprints, which contain only the signatures of operations, and the description of data and operations which belongs to the blueprint (called static members, we’ll see more details later).
In any case, Interfaces can extend interfaces – that is, imply the data and operations from another interface and add more. Classes can implement interfaces, which means that they can define the operations for their particular situation or set of data.
What’s a signature for an operation, you ask? It’s the collection of data that makes an operation uniquely identifiable: name of the operation, type returned, number of parameters received and number (and ordering) of those parameters. The name of the parameters is not taken into account for the signature, only their order and type.
Class based relationship is different from interface based relationship. There can be only one class from which information and operations are derived in Java, although there can be many interfaces. There are two kinds of classes – abstract and concrete. The abstract ones are halfway between a “regular” class and an interface: they can have both implemented and merely described operations, and data pertaining both the blueprint and the actual building (class [or interface] and object, for those who didn’t go back and read previous articles).
In any case, you can extend or implement fro many interfaces, but only extend from a single class. As every object type can extend or implement another one, then there is a neat chain all the way to the most general type, Object.
Concrete classes can’t have unimplemented operations! If you’re extending a class or implementing an interface in a concrete class (namely, one which is not identified with the “abstract” keyword), you need to implement all behavior described by the abstract classes and interfaces.
If an object type has a class or interface relationship with another object type, it can be cast from one to the other. Only the operations and data described in the target class or interface will be available for use after casting. The relationship is needed because the computer needs to know what data and operations are going to be available. All object types in Java have at least a relationship with the Object class, so everything can be cast into an Object (although not necessarily the other way around. Think about why).
If for some reason you try casting some type into another to which it has not any relationship (int to boolean, or Java.util.ArrayList to java.sql.Date), things will crash and burn as soon as the computer takes notice. Sometimes this will be at compile-time, sometimes at runtime.
To make things clearer: relationships are hierarchical. If not in the same direct line of relationships, the relationship does not exist. If you picture it as a family tree, cousins can be cast into a common uncle/aunt or grandparent, but not into each other.
Interface relationships are tools used to create an abstraction called polymorphism, which we’ll see soon. Keep your eyes peeled.