{"id":"inheritance-abstract","slug":"abstract-classes","title":"Abstract classes and abstract methods","text":"Step 2's program made `new Instrument()`, a \"shaker\". But a music school has no instruments that are just instruments: each one is a flute, a drum, a violin. And some methods can't be written for \"an instrument\" at all. What sound does an instrument make?\n\nJava has a way to say this: an **abstract class**. It's a class made only to be extended. You can't create an object of it with `new`, and it can leave methods for its subclasses to write.\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Instrument> band = new ArrayList<>();\n        band.add(new Flute(\"Silver flute\"));\n        band.add(new Drum(\"Snare drum\"));\n        for (Instrument instrument : band) {\n            instrument.play();\n        }\n    }\n}\n// ==== Instrument.java ====\npublic abstract class Instrument {\n    private String name;\n\n    public Instrument(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public abstract String sound();\n\n    public void play() {\n        System.out.println(this.name + \": \" + this.sound());\n    }\n}\n// ==== Flute.java ====\npublic class Flute extends Instrument {\n    public Flute(String name) {\n        super(name);\n    }\n\n    @Override\n    public String sound() {\n        return \"fweee\";\n    }\n}\n// ==== Drum.java ====\npublic class Drum extends Instrument {\n    public Drum(String name) {\n        super(name);\n    }\n\n    @Override\n    public String sound() {\n        return \"boom boom\";\n    }\n}\n```\n\n```output\nSilver flute: fweee\nSnare drum: boom boom\n```\n\n- `public abstract class Instrument` makes Instrument abstract.\n- `public abstract String sound();` is an **abstract method**: a header followed by a semicolon, with no body. It says that every instrument has a `sound()` that returns a String, and leaves the code to the subclasses.\n- Everything else is as in any class: an instance variable, a constructor, which the subclasses call with `super(name)`, and ordinary methods such as `getName` and `play`.\n- `play` is written once, in Instrument, and calls `sound()`. As in step 6, the version that runs is the object's own: the flute's, then the drum's.\n- Variables and lists of the abstract type are fine: `ArrayList<Instrument>` holds flutes and drums. It just can never hold an object that is only an Instrument.\n\n### No new\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Instrument mystery = new Instrument(\"Mystery\");\n        mystery.play();\n    }\n}\n// ==== Instrument.java ====\npublic abstract class Instrument {\n    private String name;\n\n    public Instrument(String name) {\n        this.name = name;\n    }\n\n    public abstract String sound();\n\n    public void play() {\n        System.out.println(this.name + \": \" + this.sound());\n    }\n}\n```\n\n```javac\nMain.java:3: error: Instrument is abstract; cannot be instantiated\n        Instrument mystery = new Instrument(\"Mystery\");\n                             ^\n1 error\n```\n\nThink about what `mystery.play()` would have to do: call `sound()`, which has no code to run. So Java doesn't let an abstract class's object exist on its own. Instrument's constructor still runs, but only as the first part of building a Flute or a Drum.\n\n### A subclass must write the missing methods\n\nA class that extends Instrument must write every abstract method, or it doesn't compile. Here a harp forgot its sound:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Harp harp = new Harp(\"Concert harp\");\n        harp.play();\n    }\n}\n// ==== Instrument.java ====\npublic abstract class Instrument {\n    private String name;\n\n    public Instrument(String name) {\n        this.name = name;\n    }\n\n    public abstract String sound();\n\n    public void play() {\n        System.out.println(this.name + \": \" + this.sound());\n    }\n}\n// ==== Harp.java ====\npublic class Harp extends Instrument {\n    public Harp(String name) {\n        super(name);\n    }\n}\n```\n\n```javac\nHarp.java:1: error: Harp is not abstract and does not override abstract method sound() in Instrument\npublic class Harp extends Instrument {\n       ^\n1 error\n```\n\n- The fix is to write Harp's `sound()`. javac's other way out, making Harp abstract too, means no harps could be made either. That fits only for a group of instruments, such as a `StringInstrument` between Instrument and Harp that leaves `sound()` to each of its own subclasses.\n- Only an abstract class may have abstract methods. A plain class with an abstract method doesn't compile.\n- A class can be abstract without any abstract methods. Then `abstract` just forbids `new`.\n\n### Why not an ordinary class?\n\nInstrument could be a plain class, with `sound()` returning `\"\"` as a placeholder. Then `new Instrument(...)` would make an instrument without a sound, and a subclass that forgot to override `sound()` would quietly play nothing. The abstract method turns both mistakes into errors that javac catches, and it tells anyone reading the class what a subclass must provide.\n\nModule 35's interfaces take this idea further: they list methods that a class promises to have, without being its superclass.\n","task":"The courier makes `Shipment` abstract: every shipment has a price, but there's no price for \"a shipment\" in general. `Shipment.java` and `Letter.java` are ready. In `Pallet.java`, write the class `Pallet`, which extends Shipment:\n\n- a constructor `Pallet(String code, int boxes)`\n- `price()`, with `@Override` above it, which returns 20 dollars plus 5 for every box\n\nThe check runs:\n\n```java\nShipment pallet = new Pallet(\"T-40\", 6);\nSystem.out.println(pallet.label());\nSystem.out.println(new Letter(\"L-3\").label());\nSystem.out.println(new Pallet(\"T-41\", 0).price());\n```\n\nand expects:\n\n```\nT-40: 50 dollars\nL-3: 2 dollars\n20\n```\n","kind":"code","seed":"// ==== Pallet.java ====\npublic class Pallet {\n\n}\n\n// ==== Shipment.java ====\npublic abstract class Shipment {\n    private String code;\n\n    public Shipment(String code) {\n        this.code = code;\n    }\n\n    public String getCode() {\n        return this.code;\n    }\n\n    public abstract int price();\n\n    public String label() {\n        return this.code + \": \" + this.price() + \" dollars\";\n    }\n}\n\n// ==== Letter.java ====\npublic class Letter extends Shipment {\n    public Letter(String code) {\n        super(code);\n    }\n\n    @Override\n    public int price() {\n        return 2;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Shipment pallet = new Pallet(\"T-40\", 6);\n        System.out.println(pallet.label());\n        System.out.println(new Letter(\"L-3\").label());\n        System.out.println(new Pallet(\"T-41\", 0).price());\n    }\n}\n","solution":"// ==== Pallet.java ====\npublic class Pallet extends Shipment {\n    private int boxes;\n\n    public Pallet(String code, int boxes) {\n        super(code);\n        this.boxes = boxes;\n    }\n\n    @Override\n    public int price() {\n        return 20 + 5 * this.boxes;\n    }\n}\n\n// ==== Shipment.java ====\npublic abstract class Shipment {\n    private String code;\n\n    public Shipment(String code) {\n        this.code = code;\n    }\n\n    public String getCode() {\n        return this.code;\n    }\n\n    public abstract int price();\n\n    public String label() {\n        return this.code + \": \" + this.price() + \" dollars\";\n    }\n}\n\n// ==== Letter.java ====\npublic class Letter extends Shipment {\n    public Letter(String code) {\n        super(code);\n    }\n\n    @Override\n    public int price() {\n        return 2;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Shipment pallet = new Pallet(\"T-40\", 6);\n        System.out.println(pallet.label());\n        System.out.println(new Letter(\"L-3\").label());\n        System.out.println(new Pallet(\"T-41\", 0).price());\n    }\n}\n","hints":["Letter shows the pattern: `extends Shipment`, a constructor that starts with `super(code);`, and `price()` with `@Override`. Pallet also keeps its number of boxes.","`price()` returns `20 + 5 * this.boxes`. `label()` is Shipment's, and it calls the pallet's own `price()`."],"tests":[{"name":"Test 1","stdin":"","call":"Shipment pallet = new Pallet(\"T-40\", 6);\nSystem.out.println(pallet.label());\nSystem.out.println(new Letter(\"L-3\").label());\nSystem.out.println(new Pallet(\"T-41\", 0).price());\n","expect":"T-40: 50 dollars\nL-3: 2 dollars\n20","hidden":false},{"name":"Test 2","stdin":"","call":"Pallet big = new Pallet(\"T-99\", 40);\nSystem.out.println(big.getCode() + \" \" + big.price());\nSystem.out.println(new Pallet(\"T-2\", 1).label());\n","expect":"T-99 220\nT-2: 25 dollars","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Shipment> van = new ArrayList<>();\nvan.add(new Letter(\"L-1\"));\nvan.add(new Pallet(\"T-5\", 3));\nvan.add(new Pallet(\"T-6\", 2));\nint total = 0;\nfor (Shipment item : van) {\n    total += item.price();\n}\nSystem.out.println(total);\n","expect":"67","hidden":true}],"require":[{"pattern":"\\bclass\\s+Pallet\\s+extends\\s+Shipment\\b","message":"Write the header as `public class Pallet extends Shipment`."},{"pattern":"@Override\\s+public\\s+int\\s+price\\s*\\(\\s*\\)","min":2,"message":"Write Pallet's `public int price()`, with `@Override` above it."}],"forbid":[],"more":[{"task":"In a museum, every exhibit is kept in some room, but which room depends on the kind of exhibit. Fill in the two blanks, the same word in both, so that `Exhibit` can't be created with `new`, and its subclasses must write `room()`.\n","kind":"fill","seed":"public class Main {\n    public static void main(String[] args) {\n        Exhibit lion = new Statue(\"Marble lion\", 900);\n        Exhibit bust = new Statue(\"Bronze bust\", 40);\n        System.out.println(lion.label());\n        System.out.println(bust.label());\n    }\n}\n// ==== Exhibit.java ====\npublic [[abstract]] class Exhibit {\n    private String name;\n\n    public Exhibit(String name) {\n        this.name = name;\n    }\n\n    public [[abstract]] String room();\n\n    public String label() {\n        return this.name + \", in the \" + this.room();\n    }\n}\n// ==== Statue.java ====\npublic class Statue extends Exhibit {\n    private int kilograms;\n\n    public Statue(String name, int kilograms) {\n        super(name);\n        this.kilograms = kilograms;\n    }\n\n    @Override\n    public String room() {\n        if (this.kilograms > 500) {\n            return \"ground floor hall\";\n        }\n        return \"sculpture gallery\";\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Exhibit lion = new Statue(\"Marble lion\", 900);\n        Exhibit bust = new Statue(\"Bronze bust\", 40);\n        System.out.println(lion.label());\n        System.out.println(bust.label());\n    }\n}\n// ==== Exhibit.java ====\npublic abstract class Exhibit {\n    private String name;\n\n    public Exhibit(String name) {\n        this.name = name;\n    }\n\n    public abstract String room();\n\n    public String label() {\n        return this.name + \", in the \" + this.room();\n    }\n}\n// ==== Statue.java ====\npublic class Statue extends Exhibit {\n    private int kilograms;\n\n    public Statue(String name, int kilograms) {\n        super(name);\n        this.kilograms = kilograms;\n    }\n\n    @Override\n    public String room() {\n        if (this.kilograms > 500) {\n            return \"ground floor hall\";\n        }\n        return \"sculpture gallery\";\n    }\n}\n","hints":["The same word goes before `class` in the class's header, and before the return type of a method that has no body.","`public abstract class Exhibit` and `public abstract String room();`. A method without a body is allowed only when it's abstract, and only an abstract class may have one."],"tests":[{"name":"Output","stdin":"","expect":"Marble lion, in the ground floor hall\nBronze bust, in the sculpture gallery","hidden":false}],"require":[],"forbid":[]},{"task":"Now write an abstract class yourself. The library's films and audiobooks are ready in `Film.java` and `Audiobook.java`: each extends `LibraryItem`, hands its title to `super(title)`, and overrides `loanDays()`. In `LibraryItem.java`, write the abstract class `LibraryItem`, with:\n\n- a private title, and a constructor `LibraryItem(String title)`\n- `getTitle()`\n- an abstract method `int loanDays()`\n- `dueDay(int today)`, which returns the number of the day the item is due back: today's number plus the item's loan days\n\nThe check runs:\n\n```java\nLibraryItem film = new Film(\"Night Train\");\nLibraryItem audio = new Audiobook(\"Salt and Stars\");\nSystem.out.println(film.getTitle() + \": day \" + film.dueDay(10));\nSystem.out.println(audio.getTitle() + \": day \" + audio.dueDay(10));\n```\n\nand expects:\n\n```\nNight Train: day 17\nSalt and Stars: day 24\n```\n","kind":"code","seed":"// ==== LibraryItem.java ====\npublic class LibraryItem {\n\n}\n\n// ==== Film.java ====\npublic class Film extends LibraryItem {\n    public Film(String title) {\n        super(title);\n    }\n\n    @Override\n    public int loanDays() {\n        return 7;\n    }\n}\n\n// ==== Audiobook.java ====\npublic class Audiobook extends LibraryItem {\n    public Audiobook(String title) {\n        super(title);\n    }\n\n    @Override\n    public int loanDays() {\n        return 14;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        LibraryItem film = new Film(\"Night Train\");\n        LibraryItem audio = new Audiobook(\"Salt and Stars\");\n        System.out.println(film.getTitle() + \": day \" + film.dueDay(10));\n        System.out.println(audio.getTitle() + \": day \" + audio.dueDay(10));\n    }\n}\n","solution":"// ==== LibraryItem.java ====\npublic abstract class LibraryItem {\n    private String title;\n\n    public LibraryItem(String title) {\n        this.title = title;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public abstract int loanDays();\n\n    public int dueDay(int today) {\n        return today + this.loanDays();\n    }\n}\n\n// ==== Film.java ====\npublic class Film extends LibraryItem {\n    public Film(String title) {\n        super(title);\n    }\n\n    @Override\n    public int loanDays() {\n        return 7;\n    }\n}\n\n// ==== Audiobook.java ====\npublic class Audiobook extends LibraryItem {\n    public Audiobook(String title) {\n        super(title);\n    }\n\n    @Override\n    public int loanDays() {\n        return 14;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        LibraryItem film = new Film(\"Night Train\");\n        LibraryItem audio = new Audiobook(\"Salt and Stars\");\n        System.out.println(film.getTitle() + \": day \" + film.dueDay(10));\n        System.out.println(audio.getTitle() + \": day \" + audio.dueDay(10));\n    }\n}\n","hints":["The header is `public abstract class LibraryItem {`. The title, the constructor and `getTitle()` are as in any class.","The abstract method is `public abstract int loanDays();`, with no body. `dueDay` returns `today + this.loanDays()`, and each object's own `loanDays` runs."],"tests":[{"name":"Test 1","stdin":"","call":"LibraryItem film = new Film(\"Night Train\");\nLibraryItem audio = new Audiobook(\"Salt and Stars\");\nSystem.out.println(film.getTitle() + \": day \" + film.dueDay(10));\nSystem.out.println(audio.getTitle() + \": day \" + audio.dueDay(10));\n","expect":"Night Train: day 17\nSalt and Stars: day 24","hidden":false},{"name":"Test 2","stdin":"","call":"ArrayList<LibraryItem> bag = new ArrayList<>();\nbag.add(new Audiobook(\"Winter Roads\"));\nbag.add(new Film(\"Blue Hour\"));\nfor (LibraryItem item : bag) {\n    System.out.println(item.getTitle() + \" \" + item.loanDays() + \" \" + item.dueDay(0) + \" \" + item.dueDay(300));\n}\n","expect":"Winter Roads 14 14 314\nBlue Hour 7 7 307","hidden":true}],"require":[{"pattern":"\\babstract\\s+class\\s+LibraryItem\\b","message":"Make the class abstract: `public abstract class LibraryItem`."},{"pattern":"\\babstract\\s+int\\s+loanDays\\s*\\(\\s*\\)\\s*;","message":"Declare `loanDays` as an abstract method, with no body: `public abstract int loanDays();`."}],"forbid":[]}]}