Skip to content

Latest commit

 

History

History
76 lines (73 loc) · 4.08 KB

implementation_inheritance.md

File metadata and controls

76 lines (73 loc) · 4.08 KB

Implementation inheritance

Consider the following class Color, whose instances represent colors defined by their red, green, and blue components:

public class Color {
    public final int red, green, blue;
    public Color(int red, int green, int blue) {
        this.red = red;
        this.green = green;
        this.blue = blue;
    }
    public int getHue() { /* ... */ }
    public int getSaturation() { /* ... */ }
    public int getValue() { /* ... */ }
    @Override
    public String toString() {
        return "rgb(" + red + ", " + green + ", " + blue + ")";
    }
    @Override
    public boolean equals(Object other) {
        return
            other.getClass() == getClass() &&
            ((Color)other).red == red &&
            ((Color)other).green == green &&
            ((Color)other).blue == blue;
    }
    @Override
    public int hashCode() {
        return Objects.hash(red, green, blue);
    }
}

Often, this class is sufficient. But sometimes, we need to additionally store a transparency value. Instead of duplicating the existing functionality of Color, we can declare class TransparentColor as a subclass of Color:

public class TransparentColor extends Color {
    public final int transparency;
    public TransparentColor(int red, int green, int blue, int transparency) {
        super(red, green, blue);
        this.transparency = transparency;
    }
    @Override
    public String toString() {
        return
            "rgba(" + red + ", " + green + ", " + blue + ", " + transparency + ")";
    }
    @Override
    public boolean equals(Object other) {
        return
            super.equals(other) &&
            ((TransparentColor)other).transparency == transparency;
    }
    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), transparency);
    }
}

Notice the following:

  • Class TransparentColor inherits the instance (i.e. non-static) fields red, green, and blue from class Color. This means that for each instance of class TransparentColor, the computer stores four values: the values for fields red, green, blue, and transparency.
  • Java requires that a constructor first initialize the superclass fields. Typically, this means calling a superclass constructor, using the special syntax super(...). If no explicit super(...) call is written at the start of a constructor, an implicit zero-argument super() call is inserted by the compiler. If the superclass has no zero-argument constructor, the compiler reports an error.
  • The implementation of method equals in class TransparentColor reuses the implementation of equals in class Color by calling it using the special super.M(...) syntax. In contrast to regular instance method calls, super calls are statically bound: the super.equals call in class TransparentColor is always bound to method equals in class Color.
  • Since method equals in class Color checks that this.getClass() equals other.getClass(), we know that after the call of this method in method equals of class TransparentColor returns true, other is an instance of of class TransparentColor so we can safely cast it to type TransparentColor.
  • Methods getHue, getSaturation, and getValue are simply inherited by class TransparentColor from class Color. This means that calling getHue on a TransparentColor object O executes method getHue from class Color on O. This, in turn, means that inside such an execution of method getHue, this will refer to an instance of class TransparentColor.

Fields are hidden, not overridden!

If a class D declares a field with the same name F as a field it inherits from its superclass C, the inherited field is hidden, not overridden! In that case, each object of class D has two fields named F: the one declared in class C, and the one declared in class D. When F is mentioned in class C, the field declared in class C is accessed; when F is mentioned in class D, the field declared in class D is accessed. You can access the field of class C from class D using notation super.F.