11. Inheritance Calls I
A typical multiple choice question designed to assess understanding of inheritance assigns an instance of a subclass to a variable whose type is a superclass and then asks what methods would be called.
Setup
The classes to be used in this discussion are Mammal and
Human. These are not supposed to be complete or make perfect
sense. Please forgive the weird temperature function.
public class Mammal {
    public double temperature() { return 123.4; }
}
public class Human extends Mammal {
    public double temperature() { return 98.6; }
    public void speak(String s) { /* not shown */ }
}
Example A
A Human is assigned to a Mammal variable. Can you call its speak
method?
{
    Mammal m = new Human();
    m.speak("is this ok?"); // Spoiler: nope, error
}
Discussion 1
The phrasing of this question makes it very confusing for many people. I used to teach this slogan (which is correct and may help some people):
- The true type of a variable determines which method gets
called. In this example, the true type of 
misHuman. - The declared type of a variable determines what methods you are
allowed to call. In this example, the declared type if 
misMammal. 
The thing that bothers me about this approach is that there is no logic to it; it is just a rule to follow.
Discussion 2
Another way of phrasing the same question is to create a separate function for the setup and the “action”. I think this makes the rules of which functions are allowed to be called clearer.
public static void action(Mammal m) {
    m.speak("is this ok?"); // (1) Spoiler: nope, error
}
public static void setup() {
    Human h = new Human();
    action(h); // (2)
}
action
First, an analysis of the action method. In this method, all you
know about m is that it is a Mammal. Since action is a method,
it can be called from more than one place, so the reader has no reason
to believe that m is always a Human. In fact, you should imagine
other places in the code with calls like:
action(new Mammal());
Looking at the problem this way, it should be clear that you cannot
call the speak method of the m object.
setup
The other place something can go wrong is at the site where action
is called, labeled (2) in the code. If the h object is not an
instance of Mammal, then this would be an error.
Discussion 3
The original variable is unaltered by casting.
{
    Mammal m = new Human();
    m.speak(); // (1) nope
    Human h = (Human) m;
    h.speak(); // (2) ok
    m.speak(); // (3) still nope
}
Worked Example A
The illegal code Mammal m = new Snake() corresponds to the setup code below.
This is an error at the site of the call to action because the Snake variable is
not a Mammal.
public static void setup2() {
    Snake x = new Snake();
    action(x);
}
Exercise Example B
Imagine turning code into a program using classes like Variable with
subclasses IntegerVariable and StringVariable. All Variable
objects have a name method. IntegerVariable objects have an add
method to add to the number. StringVariable objects have a prepend
method that puts text in front of what is already there.
Is the following code legal? Explain.
{
    Variable v = new IntegerVariable("a",3); // (1) code for: int a = 3;
    Variable w = new StringVariable("s","Turkey"); // (2) code for: String s = "Turkey";
    v.add(5); // (3) code for: a += 5;
    w.prepend("Republic of "); // (4) code for: s = "Republic of " + s;
}
Exercise Example C
Break the code below into a setup and action step, then analyze it. You have to know how chess pieces move to understand this example. (See links in the following paragraph if you want.)
{
    ChessPiece q = new Queen();
    q.slide_horizontally(5); // move 5 squares to the right
}
Chess explanation: a queen can move an unlimited amount of squares in
a
line. The
knight is one chess piece does not move in a straight
line. from
this you deduce that although a queen may have a  slide_horizontally
method, a generic ChessPiece should not.
Exercise Example D
Suppose there are classes Mammal, Human, and Dog. All mammals have an eat() method, humans have a talk() method, and dogs have a bark() method. Explain which parts of the following code work, and why explain the problems with the parts that do not work.
public static void setup() {
    Human h = new Human();
    Dog d = new Dog();
    Mammal m = new Dog();
    Mammal q = h;
    action(h, d, q); // (1)
    action(q, h, h); // (2)
}
public static void action(Mammal a, Mammal b, Human c) {
    a.talk(); // (3)
    a.eat();  // (4)
    b.bark(); // (5)
    c.talk(); // (6)
}
Exercise Example E
An extended example with many points to wonder about. This was used in a 20 minute in-class discussion.
Warning
This example includes several ideas not covered on this page!Setup E
public class M {
  public void f() { f("Mongoose"); }
  public void f(String x) { System.out.println(x); }
}
public class P extends M {
  public void f(String x) { System.out.println("Pretty "+x); }
  public void f(int n) { f("Pink #"+n); }
  public void g() { System.out.println("Go for it"); }
}
Questions E, written AP style
public static void questionD() {
    M y = new P();
    y.g(); // (1)
    /* 2 */
    {
        P py = (P) y; // (2)
    }
    /* 3 */
    if (y instanceof P) {
        y.g();
    }
    /* 4 */
    if (y instanceof P) {
        P by = (P) y;
        // (4a)
        py.g();
        // (4b)
        ((P) y).g();
        // (4c - only for very advanced)
        (P) y.g();
    }
    /* 5: What happens? */
    y.f();
}
Questions E, written function style
This is the same code as above, but split into a setup function and an action function. The variable names have also been changed to show the declared type of the object, which is a strategy to keep track of the information.
public static void setup() {
    P p = new P();
    action(p);
}
public static void action(M m)
{
    m.g(); // (1)
    /* 2 */
    {
        P p = (P) m; // (2)
    }
    /* 3 */
    if (m instanceof P) {
        m.g();
    }
    /* 4 */
    if (m instanceof P) {
        P p = (P) m;
        // (4a)
        p.g();
        // (4b)
        ((P) m).g();
        // (4c)
        (P) m.g();
    }
    /* 5: What happens? */
    m.f();
}