Skip to main content

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.

Section 8.7, Section 8.8