Sponsored Link •
Dynamic binding, polymorphism, and change
When you establish an inheritance relationship between two classes, you get to take advantage of dynamic binding and polymorphism. Dynamic binding means the JVM will decide at runtime which method implementation to invoke based on the class of the object. Polymorphism means you can use a variable of a superclass type to hold a reference to an object whose class is the superclass or any of its subclasses.
One of the prime benefits of dynamic binding and polymorphism is that
they can help make code easier to change. If you have a fragment of
code that uses a variable of a superclass type, such as
Fruit, you could later create a brand new subclass, such
Banana, and the old code fragment will work without
change with instances of the new subclass. If
overrides any of
Fruit's methods that are invoked by the
code fragment, dynamic binding will ensure that
implementation of those methods gets executed. This will be true even
Banana didn't exist when the code fragment
was written and compiled.
Thus, inheritance helps make code easier to change if the needed change involves adding a new subclass. This, however, is not the only kind of change you may need to make.
Changing the superclass interface
In an inheritance relationship, superclasses are often said to be "fragile," because one little change to a superclass can ripple out and require changes in many other places in the application's code. To be more specific, what is actually fragile about a superclass is its interface. If the superclass is well-designed, with a clean separation of interface and implementation in the object-oriented style, any changes to the superclass's implementation shouldn't ripple at all. Changes to the superclass's interface, however, can ripple out and break any code that uses the superclass or any of its subclasses. What's more, a change in the superclass interface can break the code that defines any of its subclasses.
For example, if you change the return type of a public method in class
Fruit (a part of
Fruit's interface), you can
break the code that invokes that method on any reference of type
Fruit or any subclass of
Fruit. In addition,
you break the code that defines any subclass of
overrides the method. Such subclasses won't compile until you go and
change the return value of the overridden method to match the changed
method in superclass
Inheritance is also sometimes said to provide "weak encapsulation,"
because if you have code that directly uses a subclass, such as
Apple, that code can be broken by changes to a superclass,
Fruit. One of the ways to look at inheritance is
that it allows subclass code to reuse superclass code. For
Apple doesn't override a method defined in its
Apple is in a sense reusing
Fruit's implementation of the method. But
Apple only "weakly encapsulates" the
code it is reusing, because changes to
can break code that directly uses