{"id":"inheritance-actual-type","slug":"actual-type","title":"The object's class decides which method runs","text":"A Film is a LibraryItem, and a SavingsAccount is a BankAccount. Java takes that literally: a variable whose type is the superclass can refer to an object of a subclass. Then which version of an overridden method runs, the one of the variable's type or the one of the object's class?\n\n### A variable of the superclass's type\n\nIn a small game, every adventurer attacks, but knights hit harder than archers:\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        Adventurer hero = new Knight(\"Oren\");\n        System.out.println(hero.attack());\n        System.out.println(hero.describe());\n\n        ArrayList<Adventurer> party = new ArrayList<>();\n        party.add(hero);\n        party.add(new Archer(\"Lyra\"));\n        party.add(new Adventurer(\"Pip\"));\n        int total = 0;\n        for (Adventurer member : party) {\n            System.out.println(member.describe());\n            total += member.attack();\n        }\n        System.out.println(\"Party total: \" + total);\n    }\n}\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" attacks for \" + this.attack();\n    }\n}\n// ==== Knight.java ====\npublic class Knight extends Adventurer {\n    public Knight(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 9;\n    }\n\n    public void raiseShield() {\n        System.out.println(this.getName() + \" raises a shield\");\n    }\n}\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    public Archer(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 6;\n    }\n}\n```\n\n```output\n9\nOren attacks for 9\nOren attacks for 9\nLyra attacks for 6\nPip attacks for 2\nParty total: 17\n```\n\n- `Adventurer hero = new Knight(\"Oren\");` compiles, because every Knight is an Adventurer: it has every method an Adventurer has.\n- `hero.attack()` gives 9, Knight's number. Java doesn't look at the variable's type to pick the version. It looks at the object the variable refers to, and that object is a Knight.\n- That holds even inside Adventurer's own code. `describe` is written in Adventurer, and calls `this.attack()`. For Oren, `this` is a Knight object, so Knight's `attack` runs. For Pip, a plain Adventurer, Adventurer's runs.\n- So one list can hold every kind of adventurer, and one loop handles them all. The loop doesn't know or care which kind each member is: each object brings its own `attack`.\n\n### The variable's type decides what you may call\n\n`hero` refers to a Knight, and a Knight can raise a shield. Still, this doesn't compile:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Adventurer hero = new Knight(\"Oren\");\n        hero.raiseShield();\n    }\n}\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n}\n// ==== Knight.java ====\npublic class Knight extends Adventurer {\n    public Knight(String name) {\n        super(name);\n    }\n\n    public void raiseShield() {\n        System.out.println(this.getName() + \" raises a shield\");\n    }\n}\n```\n\n```javac\nMain.java:4: error: cannot find symbol\n        hero.raiseShield();\n            ^\n  symbol:   method raiseShield()\n  location: variable hero of type Adventurer\n1 error\n```\n\njavac checks each call against the variable's type. It doesn't run the program, so it doesn't know which object will be in `hero` when the call happens: some other line could put an Archer there. It only knows that `hero` holds some Adventurer, and not every Adventurer has `raiseShield`. With `Knight hero = new Knight(\"Oren\");` the call compiles. (Module 36 shows how to get back to the Knight when a program needs to.)\n\nThe two rules, side by side:\n\n- The **variable's type** decides which methods you may call. javac checks it before the program runs.\n- The **object's class** decides which version of a method runs. That's settled while the program runs.\n\nThe other way around doesn't work at all: `Knight knight = new Adventurer(\"Pip\");` doesn't compile (`incompatible types: Adventurer cannot be converted to Knight`), since an adventurer isn't necessarily a knight.\n\n### Every object is an Object\n\nEvery class inherits from Object, so a variable of type Object can refer to any object at all. Its methods are Object's, but the versions that run are the object's own:\n\n```java\nObject first = \"a String\";\nObject second = new ArrayList<String>();\nString start = \"Oak\";\nObject third = start + \"dale\";\nSystem.out.println(first);\nSystem.out.println(second);\nSystem.out.println(third.equals(\"Oakdale\"));\n```\n\n```output\na String\n[]\ntrue\n```\n\n- `println` can print any object because it takes an Object and calls its `toString`, and each object runs its own: String's gives the text, ArrayList's gives the brackets.\n- `third.equals(...)` runs String's `equals`, which compares the characters. Object's `equals` would compare with `==`, and `third` is a String built while the program runs, a different object from `\"Oakdale\"`.\n- `first.length()` wouldn't compile: `first` is an Object variable, and Object has no `length()`.\n","task":"The party again, with one change: Knight now overrides `describe` too. What does this program print?\n","kind":"predict","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Adventurer> party = new ArrayList<>();\n        party.add(new Adventurer(\"Pip\"));\n        party.add(new Archer(\"Lyra\"));\n        party.add(new Knight(\"Oren\"));\n        for (Adventurer member : party) {\n            System.out.println(member.describe());\n        }\n        Adventurer last = party.get(2);\n        System.out.println(last.attack() + party.get(0).attack());\n    }\n}\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" attacks for \" + this.attack();\n    }\n}\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    public Archer(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 6;\n    }\n}\n// ==== Knight.java ====\npublic class Knight extends Adventurer {\n    public Knight(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 9;\n    }\n\n    @Override\n    public String describe() {\n        return super.describe() + \" and raises a shield\";\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Adventurer> party = new ArrayList<>();\n        party.add(new Adventurer(\"Pip\"));\n        party.add(new Archer(\"Lyra\"));\n        party.add(new Knight(\"Oren\"));\n        for (Adventurer member : party) {\n            System.out.println(member.describe());\n        }\n        Adventurer last = party.get(2);\n        System.out.println(last.attack() + party.get(0).attack());\n    }\n}\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" attacks for \" + this.attack();\n    }\n}\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    public Archer(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 6;\n    }\n}\n// ==== Knight.java ====\npublic class Knight extends Adventurer {\n    public Knight(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 9;\n    }\n\n    @Override\n    public String describe() {\n        return super.describe() + \" and raises a shield\";\n    }\n}\n","hints":["Each member runs its own class's methods. Lyra has Adventurer's `describe`, but it calls `this.attack()`, and Lyra is an Archer.","Oren's `describe` is Knight's: it starts with Adventurer's text, with Knight's attack of 9 in it, and adds its own ending. The last line adds Oren's attack and Pip's."],"tests":[{"name":"Output","stdin":"","expect":"Pip attacks for 2\nLyra attacks for 6\nOren attacks for 9 and raises a shield\n11","hidden":false}],"require":[],"forbid":[],"lines":["Pip attacks for 2","Lyra attacks for 6","Oren attacks for 9 and raises a shield","11"],"more":[{"task":"The game wants to know who hits hardest. `Adventurer.java`, `Knight.java` and `Archer.java` are the lesson's. In `Main.java`, write the method `strongest(ArrayList<Adventurer> party)`, which returns the name of the member whose `attack()` is the highest. When several are equally strong, return the first of them. For an empty party, return `nobody`. The check runs:\n\n```java\nArrayList<Adventurer> party = new ArrayList<>();\nparty.add(new Archer(\"Lyra\"));\nparty.add(new Adventurer(\"Pip\"));\nparty.add(new Knight(\"Oren\"));\nSystem.out.println(strongest(party));\n```\n\nand expects:\n\n```\nOren\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Adventurer> party = new ArrayList<>();\n        party.add(new Archer(\"Lyra\"));\n        party.add(new Adventurer(\"Pip\"));\n        party.add(new Knight(\"Oren\"));\n        System.out.println(strongest(party));\n    }\n\n    // Write the method strongest here.\n}\n\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" attacks for \" + this.attack();\n    }\n}\n\n// ==== Knight.java ====\npublic class Knight extends Adventurer {\n    public Knight(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 9;\n    }\n\n    public void raiseShield() {\n        System.out.println(this.getName() + \" raises a shield\");\n    }\n}\n\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    public Archer(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 6;\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Adventurer> party = new ArrayList<>();\n        party.add(new Archer(\"Lyra\"));\n        party.add(new Adventurer(\"Pip\"));\n        party.add(new Knight(\"Oren\"));\n        System.out.println(strongest(party));\n    }\n\n    public static String strongest(ArrayList<Adventurer> party) {\n        if (party.isEmpty()) {\n            return \"nobody\";\n        }\n        Adventurer best = party.get(0);\n        for (Adventurer member : party) {\n            if (member.attack() > best.attack()) {\n                best = member;\n            }\n        }\n        return best.getName();\n    }\n}\n\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" attacks for \" + this.attack();\n    }\n}\n\n// ==== Knight.java ====\npublic class Knight extends Adventurer {\n    public Knight(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 9;\n    }\n\n    public void raiseShield() {\n        System.out.println(this.getName() + \" raises a shield\");\n    }\n}\n\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    public Archer(String name) {\n        super(name);\n    }\n\n    @Override\n    public int attack() {\n        return 6;\n    }\n}\n","hints":["Return `nobody` first if `party.isEmpty()`. Otherwise keep the best member so far, starting with `party.get(0)`, and go through the party with a for-each loop.","Replace the best member only when `member.attack() > best.attack()`, with `>`, so the first of equally strong members stays. Each call runs the object's own `attack`, so the method works for knights, archers and every other kind."],"tests":[{"name":"Test 1","stdin":"","call":"ArrayList<Adventurer> party = new ArrayList<>();\nparty.add(new Archer(\"Lyra\"));\nparty.add(new Adventurer(\"Pip\"));\nparty.add(new Knight(\"Oren\"));\nSystem.out.println(strongest(party));\n","expect":"Oren","hidden":false},{"name":"Test 2","stdin":"","call":"ArrayList<Adventurer> party = new ArrayList<>();\nSystem.out.println(strongest(party));\nparty.add(new Adventurer(\"Pip\"));\nSystem.out.println(strongest(party));\nparty.add(new Archer(\"Lyra\"));\nparty.add(new Archer(\"Tam\"));\nSystem.out.println(strongest(party));\nparty.add(0, new Knight(\"Oren\"));\nparty.add(new Knight(\"Brand\"));\nSystem.out.println(strongest(party));\n","expect":"nobody\nPip\nLyra\nOren","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Adventurer> party = new ArrayList<>();\nparty.add(new Adventurer(\"Ivo\"));\nparty.add(new Adventurer(\"Jin\"));\nSystem.out.println(strongest(party));\n","expect":"Ivo","hidden":true}],"require":[{"pattern":"\\bpublic\\s+static\\s+String\\s+strongest\\s*\\(\\s*ArrayList<Adventurer>\\s+\\w+\\s*\\)","message":"Write the method as `public static String strongest(ArrayList<Adventurer> party)`."},{"pattern":"\\.attack\\s*\\(\\s*\\)","message":"Compare the members by what their `attack()` returns."}],"forbid":[]},{"task":"Here the game's Adventurer has a role, and `describe` uses both `role()` and `attack()`. In `Healer.java`, write the class `Healer`, which extends Adventurer:\n\n- a constructor `Healer(String name)`\n- `role()` overridden to return `healer`, with `@Override` above it\n- `attack()` overridden to return 1, with `@Override` above it\n- a method of its own, `heal()`, which returns 8\n\nDon't write a `describe` in Healer: Adventurer's already works for it, since it calls the object's own `role()` and `attack()`. The check runs:\n\n```java\nAdventurer mo = new Healer(\"Mo\");\nSystem.out.println(mo.describe());\nHealer ash = new Healer(\"Ash\");\nSystem.out.println(ash.heal() + \" \" + ash.attack());\n```\n\nand expects:\n\n```\nMo the healer attacks for 1\n8 1\n```\n","kind":"code","seed":"// ==== Healer.java ====\npublic class Healer {\n\n}\n\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String role() {\n        return \"adventurer\";\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" the \" + this.role() + \" attacks for \" + this.attack();\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Adventurer mo = new Healer(\"Mo\");\n        System.out.println(mo.describe());\n        Healer ash = new Healer(\"Ash\");\n        System.out.println(ash.heal() + \" \" + ash.attack());\n    }\n}\n","solution":"// ==== Healer.java ====\npublic class Healer extends Adventurer {\n    public Healer(String name) {\n        super(name);\n    }\n\n    @Override\n    public String role() {\n        return \"healer\";\n    }\n\n    @Override\n    public int attack() {\n        return 1;\n    }\n\n    public int heal() {\n        return 8;\n    }\n}\n\n// ==== Adventurer.java ====\npublic class Adventurer {\n    private String name;\n\n    public Adventurer(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String role() {\n        return \"adventurer\";\n    }\n\n    public int attack() {\n        return 2;\n    }\n\n    public String describe() {\n        return this.name + \" the \" + this.role() + \" attacks for \" + this.attack();\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Adventurer mo = new Healer(\"Mo\");\n        System.out.println(mo.describe());\n        Healer ash = new Healer(\"Ash\");\n        System.out.println(ash.heal() + \" \" + ash.attack());\n    }\n}\n","hints":["Start with `public class Healer extends Adventurer {` and a constructor whose first line is `super(name);`.","Override `public String role()` and `public int attack()`, each with `@Override` above it, and add `public int heal()`. Adventurer's `describe` calls `this.role()` and `this.attack()`, and for a Healer object those are Healer's."],"tests":[{"name":"Test 1","stdin":"","call":"Adventurer mo = new Healer(\"Mo\");\nSystem.out.println(mo.describe());\nHealer ash = new Healer(\"Ash\");\nSystem.out.println(ash.heal() + \" \" + ash.attack());\n","expect":"Mo the healer attacks for 1\n8 1","hidden":false},{"name":"Test 2","stdin":"","call":"Healer ivy = new Healer(\"Ivy\");\nSystem.out.println(ivy.getName() + \" \" + ivy.role() + \" \" + ivy.heal());\nAdventurer pip = new Adventurer(\"Pip\");\nSystem.out.println(pip.describe());\n","expect":"Ivy healer 8\nPip the adventurer attacks for 2","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Adventurer> party = new ArrayList<>();\nparty.add(new Adventurer(\"Pip\"));\nparty.add(new Healer(\"Rue\"));\nint total = 0;\nfor (Adventurer member : party) {\n    total += member.attack();\n    System.out.println(member.describe());\n}\nSystem.out.println(total);\n","expect":"Pip the adventurer attacks for 2\nRue the healer attacks for 1\n3","hidden":true}],"require":[{"pattern":"\\bclass\\s+Healer\\s+extends\\s+Adventurer\\b","message":"Write the header as `public class Healer extends Adventurer`."},{"pattern":"@Override","min":2,"message":"Put `@Override` above `role()` and `attack()`, the two methods Healer overrides."},{"pattern":"\\bString\\s+describe\\s*\\(","max":1,"message":"Don't write a `describe` in Healer: the one in Adventurer already uses Healer's `role()` and `attack()`."}],"forbid":[]}]}