Skip to main content
Logo image

Section C.18 J3: Abstract Classes, Object, Overriding and Overloading Methods

Synopsis.

  • Motivate inheritance of methods by code reuse by means of the Vec2 example.
    • Multiple variants share code. But code duplication is bad.
    • The translate method is implemented in both classes. Factor this method out into a super class BaseVec2.
    • However, setXY is not available in BaseVec.
    • Make BaseVec2 abstract and declare method setXY abstract in BaseVec2.
    • Subclasses can always override methods. CartesianVec2 could override translate and provide a more “direct” implementation.
    • Mention @override. Defer discussion to overloading.
  • Object
    • toString used to automatically convert an object to a string. Used by the + operator on strings and many other methods such as System.out.println.
    • equals() compares objects to be equal (not the same; that is done by the == operator!). We need this if we want to put objects in collections. Make small example, comparing two strings. Implement in BaseVec2.
    • equals(Vec2) would be nice but does not override equals(Object) that we inherit from Object. @override helps to make clear that we are actually overriding a method. Will cause compile error if we are overloading instead of overriding.
    • We cannot call getX from equals(Object) because the static type is too weak. instanceof allows for tests on the dynamic type and guard dynamic type casts.
    • Illustrate subtype relationship by means of a Venn diagram. Make clear that we can always weaken the static type. Strengthening it needs a dynamic cast. Draw connection to assertion lecture: weakening post-condition is always possible.
    • Using instanceof is bad style and hints at a problem in the design. Sometimes, like in equals it is however necessary. Work as much as possible with static types.
  • Overloading.
    • Define signature of method with a certain name: list of parameters including implicit this argument. Return type is not part of signature.
    • Overloading means that we have multiple methods with the same name but different signature.
    • Overloaded method is identified at compile type based on the static types of the method's arguments.
    • In contrast to overriding: identifies method to call at run time based on the dynamic types of the the first (this) argument.
    • Identification of suitable overloaded method for a call:
      1. Identify set of methods with appropriate number of parameters.
      2. From that, identify set of applicable methods; if set empty: error.
      3. From that set, identify most specific method; if not unique: error.

Sections Covered.