is-a relationship: “A circle is a shape.”
Have core members and operations shared among the ones derived from it.
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.
position | ease | box | interval | due |
---|---|---|---|---|
front | 2.50 | 3 | 6.00 | 2021-01-26T23:29:49Z |
Default action: Java automatically calls base-class Default Constructor
Must call a base class constructor that has arguments, super(...)
:
Call to base class constructor must be the first action inside the derived-class constructor.
position | ease | box | interval | due |
---|---|---|---|---|
front | 2.50 | 1 | 0.01 | 2021-01-23T15:07:10Z |
If constructing a derived instance, insert steps between step 4 and 5:
for every parent class (from top to down):
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
*/