Gyh's Braindump

Inheritance

source
DT-On Java 8

is-a relationship: “A circle is a shape.”

Base Class

Have core members and operations shared among the ones derived from it.

Derived Class

Have core members and operations inherited from base class.

PLUS custom members and operations.

OR Overriding the existing operations in the base class.

When there’re no custom members or operations in the derived class, it’s called Liskov Substitution Principle. In this case, objects of derived class and base class can be substituted in both ways.

Derived classes accept all messages accepted by the base class.

Java Inheritance

Base Class Initialization

positioneaseboxintervaldue
front2.5036.002021-01-26T23:29:49Z

Default action: Java automatically calls base-class Default Constructor

Must call a base class constructor that has arguments, super(...):

  • if base classes don’t have no-arg constructor
  • if you want to call a constructor with arguments

Call to base class constructor must be the first action inside the derived-class constructor.

Order of Constructor Calls

positioneaseboxintervaldue
front2.5010.012021-01-23T15:07:10Z

Process of creating an object

If constructing a derived instance, insert steps between step 4 and 5:

for every parent class (from top to down):

  1. execute fields definition
  2. execute the constructor
class Lettuce {
  Lettuce() { System.out.println("Lettuce()"); }
}

class Meal {
  {
    System.out.println("meal instance initialization");
  }
  Meal() { System.out.println("Meal()"); }
}

class Lunch extends Meal {
  {
    System.out.println("lunch instance initialization");
  }
  Lunch() { System.out.println("Lunch()"); }
}

class PortableLunch extends Lunch {
  {
    System.out.println("portable lunch instance initialization");
  }
  PortableLunch() {
    System.out.println("PortableLunch()");
  }
  PortableLunch(String info) {
    System.out.println(info);
  }
}

public class Sandwich extends PortableLunch {
  private Lettuce l = new Lettuce();
  public Sandwich() {
    super("por info");
    System.out.println("Sandwich()");
  }
  public static void main(String[] args) {
    new Sandwich();
  }
}

/*Output
meal instance initialization
Meal()
lunch instance initialization
Lunch()
portable lunch instance initialization
por info
Lettuce()
Sandwich()
*/

When executing the base classes' constructors, methods call are polymorphic and fields not, because Fields are not polymorphic. So it’s best to prevent calling methods in constructors unless it’s final methods.

class Glyph {
  int radius = 2;
  void draw() { System.out.println("Glyph.draw()"); }
  Glyph() {
    System.out.println("Glyph() before draw()");
    System.out.println("Glyph() before draw(), radius: " + radius);
    draw();
    System.out.println("Glyph() after draw()");
  }
}

class RoundGlyph extends Glyph {
  private int radius = 1;
  RoundGlyph(int r) {
    radius = r;
    System.out.println(
      "RoundGlyph.RoundGlyph(), radius = " + radius);
  }
  @Override
  void draw() {
    System.out.println(
      "RoundGlyph.draw(), radius = " + radius);
  }
}

public class PolyConstructors {
  public static void main(String[] args) {
    new RoundGlyph(5);
  }
}
/*Output
Glyph() before draw()
Glyph() before draw(), radius: 2
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
*/