{"id":"inheritance-overriding","slug":"overriding","title":"Overriding methods: @Override and super","text":"A subclass gets its superclass's methods, but sometimes one of them doesn't fit. A library lends most items for 21 days, but films for only 7. A film is one of the library's items, so `Film` extends `LibraryItem`, and it **overrides** the method that gives the loan period: it writes its own version, with the same header.\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        LibraryItem novel = new LibraryItem(\"The Quiet Harbor\", 2019);\n        Film film = new Film(\"Night Train\", 2021, 104);\n        System.out.println(novel);\n        System.out.println(novel.loanDays());\n        System.out.println(film);\n        System.out.println(film.loanDays());\n        System.out.println(film.getTitle());\n    }\n}\n// ==== LibraryItem.java ====\npublic class LibraryItem {\n    private String title;\n    private int year;\n\n    public LibraryItem(String title, int year) {\n        this.title = title;\n        this.year = year;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public int loanDays() {\n        return 21;\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" (\" + this.year + \")\";\n    }\n}\n// ==== Film.java ====\npublic class Film extends LibraryItem {\n    private int minutes;\n\n    public Film(String title, int year, int minutes) {\n        super(title, year);\n        this.minutes = minutes;\n    }\n\n    @Override\n    public int loanDays() {\n        return 7;\n    }\n\n    @Override\n    public String toString() {\n        return super.toString() + \", film, \" + this.minutes + \" min\";\n    }\n}\n```\n\n```output\nThe Quiet Harbor (2019)\n21\nNight Train (2021), film, 104 min\n7\nNight Train\n```\n\n- Film's `loanDays` has the same name, the same parameters (none) and the same return type as LibraryItem's. For a Film object, Film's version runs. For a plain LibraryItem, LibraryItem's version runs.\n- Film doesn't override `getTitle`, so a film uses the one it inherits.\n- LibraryItem's `toString` overrides Object's, as in step 1, and Film's `toString` overrides LibraryItem's. Java runs the version nearest to the object's own class: a Film looks in Film first, then in LibraryItem, then in Object.\n\n### @Override\n\nThe line `@Override` above a method is an **annotation**, a note for the compiler: \"this method overrides a method of a superclass\". It doesn't change what the program does. It adds a check: if no superclass has a method with that header, javac stops with an error. Here `toString` is misspelled with a small `s`:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Poster poster = new Poster(\"Night Train\");\n        System.out.println(poster);\n    }\n}\n// ==== Poster.java ====\npublic class Poster {\n    private String title;\n\n    public Poster(String title) {\n        this.title = title;\n    }\n\n    @Override\n    public String tostring() {\n        return \"Poster: \" + this.title;\n    }\n}\n```\n\n```javac\nPoster.java:8: error: method does not override or implement a method from a supertype\n    @Override\n    ^\n1 error\n```\n\nWithout `@Override`, this compiles. `tostring` is then just a new method that nobody calls, and `println` uses Object's `toString`, with its class name and hash code. With `@Override`, the mistake shows up right away. From here on, this course writes `@Override` above every method that overrides another, `toString`, `equals` and `hashCode` included. The editors that generate those methods (module 32) add it too.\n\n### super.method()\n\nFilm's `toString` starts with `super.toString()`. That calls LibraryItem's version of `toString`, on this same film, and Film adds its own part to the text. `super.` reaches the superclass's version of a method, even though Film overrides it.\n\n- It saves repeating LibraryItem's code in Film. And Film couldn't repeat it anyway: `title` and `year` are private to LibraryItem, and there's no getter for the year.\n- Without `super.`, the `toString()` inside Film's `toString` would be Film's own method again, which would call itself again, and so on, until the program crashes with a `StackOverflowError`.\n- A subclass can call `super.someMethod()` in any of its methods, and at any point in the method, not only on the first line. (That rule is for `super(...)` in a constructor.)\n\n### Overriding or overloading?\n\nModule 21's overloading was two methods with the same name but different parameters, side by side in one class. Overriding is a method with the same name *and* the same parameters, in a subclass: for the subclass's objects, it takes the place of the superclass's version.\n\nThat's the trap step 1 warned about. `equals(Object compared)` overrides Object's `equals`. `equals(Exhibit compared)` has different parameters, so it overloads it: lists and maps never call it. `@Override` catches this mistake too, since the second one doesn't override anything.\n","task":"The library also lends audiobooks, for 14 days. `LibraryItem.java` is ready. In `Audiobook.java`, override two methods, each with `@Override` above it:\n\n- `loanDays()`, which returns 14\n- `toString()`, which returns LibraryItem's text, followed by `, read by ` and the narrator's name. LibraryItem has no getter for the year, so use `super.toString()`.\n\nThe check runs:\n\n```java\nAudiobook audio = new Audiobook(\"Salt and Stars\", 2016, \"Ruth Obi\");\nSystem.out.println(audio);\nSystem.out.println(audio.loanDays());\nLibraryItem novel = new LibraryItem(\"The Quiet Harbor\", 2019);\nSystem.out.println(novel + \", \" + novel.loanDays() + \" days\");\n```\n\nand expects:\n\n```\nSalt and Stars (2016), read by Ruth Obi\n14\nThe Quiet Harbor (2019), 21 days\n```\n","kind":"code","seed":"// ==== Audiobook.java ====\npublic class Audiobook extends LibraryItem {\n    private String narrator;\n\n    public Audiobook(String title, int year, String narrator) {\n        super(title, year);\n        this.narrator = narrator;\n    }\n\n    // Override loanDays and toString here.\n}\n\n// ==== LibraryItem.java ====\npublic class LibraryItem {\n    private String title;\n    private int year;\n\n    public LibraryItem(String title, int year) {\n        this.title = title;\n        this.year = year;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public int loanDays() {\n        return 21;\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" (\" + this.year + \")\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Audiobook audio = new Audiobook(\"Salt and Stars\", 2016, \"Ruth Obi\");\n        System.out.println(audio);\n        System.out.println(audio.loanDays());\n        LibraryItem novel = new LibraryItem(\"The Quiet Harbor\", 2019);\n        System.out.println(novel + \", \" + novel.loanDays() + \" days\");\n    }\n}\n","solution":"// ==== Audiobook.java ====\npublic class Audiobook extends LibraryItem {\n    private String narrator;\n\n    public Audiobook(String title, int year, String narrator) {\n        super(title, year);\n        this.narrator = narrator;\n    }\n\n    @Override\n    public int loanDays() {\n        return 14;\n    }\n\n    @Override\n    public String toString() {\n        return super.toString() + \", read by \" + this.narrator;\n    }\n}\n\n// ==== LibraryItem.java ====\npublic class LibraryItem {\n    private String title;\n    private int year;\n\n    public LibraryItem(String title, int year) {\n        this.title = title;\n        this.year = year;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public int loanDays() {\n        return 21;\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" (\" + this.year + \")\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Audiobook audio = new Audiobook(\"Salt and Stars\", 2016, \"Ruth Obi\");\n        System.out.println(audio);\n        System.out.println(audio.loanDays());\n        LibraryItem novel = new LibraryItem(\"The Quiet Harbor\", 2019);\n        System.out.println(novel + \", \" + novel.loanDays() + \" days\");\n    }\n}\n","hints":["Each method has `@Override` on the line above it, and the same header as LibraryItem's: `public int loanDays()` and `public String toString()`.","`toString` returns `super.toString() + \", read by \" + this.narrator`. `super.toString()` gives LibraryItem's text, title and year."],"tests":[{"name":"Test 1","stdin":"","call":"Audiobook audio = new Audiobook(\"Salt and Stars\", 2016, \"Ruth Obi\");\nSystem.out.println(audio);\nSystem.out.println(audio.loanDays());\nLibraryItem novel = new LibraryItem(\"The Quiet Harbor\", 2019);\nSystem.out.println(novel + \", \" + novel.loanDays() + \" days\");\n","expect":"Salt and Stars (2016), read by Ruth Obi\n14\nThe Quiet Harbor (2019), 21 days","hidden":false},{"name":"Test 2","stdin":"","call":"Audiobook audio = new Audiobook(\"Winter Roads\", 1998, \"Sam Cole\");\nSystem.out.println(\"Due in \" + audio.loanDays() + \" days: \" + audio);\nSystem.out.println(audio.getTitle());\n","expect":"Due in 14 days: Winter Roads (1998), read by Sam Cole\nWinter Roads","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Audiobook> shelf = new ArrayList<>();\nshelf.add(new Audiobook(\"A\", 2000, \"B\"));\nshelf.add(new Audiobook(\"Tides\", 2023, \"Nia Hale\"));\nSystem.out.println(shelf);\n","expect":"[A (2000), read by B, Tides (2023), read by Nia Hale]","hidden":true}],"require":[{"pattern":"@Override","min":3,"message":"Put `@Override` above both of Audiobook's methods, so that javac checks that they really override LibraryItem's."},{"pattern":"\\bsuper\\s*\\.\\s*toString\\s*\\(","message":"Start Audiobook's text with LibraryItem's, from `super.toString()`."}],"forbid":[],"more":[{"task":"A museum runs day tours and night tours. `NightTour` overrides both of Tour's methods, and calls Tour's version in each. What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        NightTour night = new NightTour();\n        night.start();\n        night.end();\n        Tour day = new Tour();\n        day.start();\n    }\n}\n// ==== Tour.java ====\npublic class Tour {\n    public void start() {\n        System.out.println(\"Meet at the entrance\");\n    }\n\n    public void end() {\n        System.out.println(\"Return the headsets\");\n    }\n}\n// ==== NightTour.java ====\npublic class NightTour extends Tour {\n    @Override\n    public void start() {\n        System.out.println(\"Hand out flashlights\");\n        super.start();\n    }\n\n    @Override\n    public void end() {\n        super.end();\n        System.out.println(\"Lock the side door\");\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        NightTour night = new NightTour();\n        night.start();\n        night.end();\n        Tour day = new Tour();\n        day.start();\n    }\n}\n// ==== Tour.java ====\npublic class Tour {\n    public void start() {\n        System.out.println(\"Meet at the entrance\");\n    }\n\n    public void end() {\n        System.out.println(\"Return the headsets\");\n    }\n}\n// ==== NightTour.java ====\npublic class NightTour extends Tour {\n    @Override\n    public void start() {\n        System.out.println(\"Hand out flashlights\");\n        super.start();\n    }\n\n    @Override\n    public void end() {\n        super.end();\n        System.out.println(\"Lock the side door\");\n    }\n}\n","hints":["A NightTour runs NightTour's versions. Each one prints its own line and calls Tour's version with `super.`, in the order the lines are written.","In `start`, NightTour's own line comes before `super.start()`. In `end`, it comes after `super.end()`. The plain Tour runs only Tour's `start`."],"tests":[{"name":"Output","stdin":"","expect":"Hand out flashlights\nMeet at the entrance\nReturn the headsets\nLock the side door\nMeet at the entrance","hidden":false}],"require":[],"forbid":[],"lines":["Hand out flashlights","Meet at the entrance","Return the headsets","Lock the side door","Meet at the entrance"]},{"task":"The library keeps a list of returned magazines. `Magazine` has an `equals`, and it gives the right answer when you call it yourself, but the list's `contains` and `indexOf` never use it: the program prints `false` and `-1`. Put `@Override` above `equals` and see what javac says. Then fix the header, and the rest of the method, so that `equals` overrides Object's: the classic way, with `instanceof` and a cast. The program should print:\n\n```\ntrue\n0\ntrue\n```\n","kind":"code","seed":"// ==== Magazine.java ====\nimport java.util.Objects;\n\npublic class Magazine {\n    private String title;\n    private int issue;\n\n    public Magazine(String title, int issue) {\n        this.title = title;\n        this.issue = issue;\n    }\n\n    public boolean equals(Magazine other) {\n        return this.title.equals(other.title) && this.issue == other.issue;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(this.title, this.issue);\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" #\" + this.issue;\n    }\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Magazine> returned = new ArrayList<>();\n        returned.add(new Magazine(\"Sky Watch\", 12));\n        returned.add(new Magazine(\"Garden Days\", 3));\n        System.out.println(returned.contains(new Magazine(\"Garden Days\", 3)));\n        System.out.println(returned.indexOf(new Magazine(\"Sky Watch\", 12)));\n        Magazine mine = new Magazine(\"Sky Watch\", 12);\n        System.out.println(mine.equals(new Magazine(\"Sky Watch\", 12)));\n    }\n}\n","solution":"// ==== Magazine.java ====\nimport java.util.Objects;\n\npublic class Magazine {\n    private String title;\n    private int issue;\n\n    public Magazine(String title, int issue) {\n        this.title = title;\n        this.issue = issue;\n    }\n\n    @Override\n    public boolean equals(Object compared) {\n        if (this == compared) {\n            return true;\n        }\n        if (!(compared instanceof Magazine)) {\n            return false;\n        }\n        Magazine other = (Magazine) compared;\n        return this.title.equals(other.title) && this.issue == other.issue;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(this.title, this.issue);\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" #\" + this.issue;\n    }\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Magazine> returned = new ArrayList<>();\n        returned.add(new Magazine(\"Sky Watch\", 12));\n        returned.add(new Magazine(\"Garden Days\", 3));\n        System.out.println(returned.contains(new Magazine(\"Garden Days\", 3)));\n        System.out.println(returned.indexOf(new Magazine(\"Sky Watch\", 12)));\n        Magazine mine = new Magazine(\"Sky Watch\", 12);\n        System.out.println(mine.equals(new Magazine(\"Sky Watch\", 12)));\n    }\n}\n","hints":["With `@Override`, javac says the method doesn't override anything: `equals(Magazine other)` has a different parameter from Object's `equals(Object)`, so it's an overload, and the list calls Object's version.","Write it as `public boolean equals(Object compared)`: `true` for `this == compared`, `false` when `!(compared instanceof Magazine)`, and otherwise `Magazine other = (Magazine) compared;` and the comparison that's there now."],"tests":[{"name":"The program's output","stdin":"","expect":"true\n0\ntrue","hidden":false},{"name":"Test 2","stdin":"","call":"Magazine one = new Magazine(\"Sky Watch\", 12);\nSystem.out.println(one.equals(new Magazine(\"Sky Watch\", 13)) + \" \" + one.equals(new Magazine(\"Sea Watch\", 12)));\nSystem.out.println(one.equals(\"Sky Watch #12\") + \" \" + one.equals(null) + \" \" + one.equals(one));\n","expect":"false false\nfalse false true","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Magazine> pile = new ArrayList<>();\npile.add(new Magazine(\"Garden Days\", 3));\npile.add(new Magazine(\"Garden Days\", 4));\npile.remove(new Magazine(\"Garden Days\", 3));\nSystem.out.println(pile);\nHashMap<Magazine, Integer> copies = new HashMap<>();\ncopies.put(new Magazine(\"Sky Watch\", 1), 5);\nSystem.out.println(copies.get(new Magazine(\"Sky Watch\", 1)));\n","expect":"[Garden Days #4]\n5","hidden":true}],"require":[{"pattern":"@Override\\s+public\\s+boolean\\s+equals\\s*\\(\\s*Object\\s+\\w+\\s*\\)","message":"Write `@Override` and then the header `public boolean equals(Object compared)`, so that it overrides Object's `equals`."},{"pattern":"\\binstanceof\\s+Magazine\\b","message":"Check with `instanceof Magazine` that the compared object is a magazine, before the cast."}],"forbid":[]}]}