Version without JavaScript, read-only: workshops, quizzes and running code are not available here. Full version · Catalogue · Sign in
Lecture notes · chapter 2
Summary of the first lecture: relationships, inheritance and interfaces
The three notions of the first lecture, and two common mistakes that go with them, checked by running the code.
The first lecture had three sequences, each devoted to one notion. The three definitions written on the board during the lecture are repeated below.
What final forbids
In the following example, the duck's wing is a private final field. One might therefore think that it is protected.
Before running the program, try to predict what the second line will print.
Final.java
class Aile {
boolean cassee = false;
}
class Canard {
private final Aile gauche; // “final”: it is the REFERENCE that is frozen
Canard(Aile gauche) {
this.gauche = gauche;
}
boolean peutVoler() {
return !gauche.cassee;
}
}
class Demo {
public static void main(String[] args) {
Aile aile = new Aile();
Canard gerard = new Canard(aile);
System.out.println("au départ, Gérard vole : " + gerard.peutVoler());
aile.cassee = true; // we break the wing without touching the final field
System.out.println("après l'accident : " + gerard.peutVoler());
}
}
A workshop goes here: you write and run code in it. It requires JavaScript.
After running: the explanation
The program prints false. The caller kept a reference to the wing and modified it without touching the final field, which did not prevent it.
To see what final forbids, you have to write code inside the Canard class itself, because from main it is private that would prevent access to the field. Add to Canard the method void changerAile(Aile neuve) { gauche = neuve; }: the compiler rejects it with the message The final field Canard.gauche cannot be assigned. final only forbids replacing the reference.
Declared type, actual type and the method called
The example has two classes and a single method override.
c is declared CanardEnPlastique but contains a CanardSwag. Before running the program, try to predict which of the two shouts.
Typage.java
class CanardEnPlastique {
public String crier() { return "coin"; }
}
class CanardSwag extends CanardEnPlastique {
@Override public String crier() { return "yo"; }
}
class Demo {
public static void main(String[] args) {
CanardEnPlastique c = new CanardSwag();
// Declared type: CanardEnPlastique. Actual type: CanardSwag.
System.out.println("c.crier() donne : " + c.crier());
Object o = new CanardSwag();
System.out.println("o.getClass() : " + o.getClass().getSimpleName());
// Uncomment the next line: the compiler refuses, even though
// the object knows perfectly well how to shout.
// System.out.println(o.crier());
}
}
A workshop goes here: you write and run code in it. It requires JavaScript.
After running: the explanation
c.crier() prints yo: the method executed is that of the actual object. o.getClass() also confirms that the object really is a CanardSwag.
Then uncomment the last line and run again. The compiler prints:
The method crier() is undefined for the type Object
The object does have a crier() method, as getClass() has just shown, but the compiler only takes the declared type into account, and Object has no crier() method.