{"id":"inheritance-is-a","slug":"is-a-has-a","title":"When to inherit: is a, or has a?","text":"`extends` is easy to write, and it saves code, so it's tempting to use it whenever one class could use another's methods. But it says something strong: every object of the subclass *is* an object of the superclass, and can be used wherever one is expected (step 6). When that isn't true, inheritance causes trouble.\n\n### A misuse\n\nA courier's parcels need the street and city they go to. `Address` already has a street, a city, a getter and a `toString`, so someone writes `Parcel extends Address` to get them all for free:\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        Parcel parcel = new Parcel(\"9 Dock Road\", \"Hull\", 1800);\n        System.out.println(parcel.getCity() + \", \" + parcel.getGrams() + \" g\");\n        System.out.println(parcel);\n\n        ArrayList<Address> friends = new ArrayList<>();\n        friends.add(new Address(\"12 Oak Road\", \"York\"));\n        friends.add(parcel);\n        System.out.println(friends.size() + \" addresses\");\n    }\n}\n// ==== Address.java ====\npublic class Address {\n    private String street;\n    private String city;\n\n    public Address(String street, String city) {\n        this.street = street;\n        this.city = city;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    @Override\n    public String toString() {\n        return this.street + \", \" + this.city;\n    }\n}\n// ==== Parcel.java ====\npublic class Parcel extends Address {\n    private int grams;\n\n    public Parcel(String street, String city, int grams) {\n        super(street, city);\n        this.grams = grams;\n    }\n\n    public int getGrams() {\n        return this.grams;\n    }\n}\n```\n\n```output\nHull, 1800 g\n9 Dock Road, Hull\n2 addresses\n```\n\nIt compiles and runs, and that's the trouble. The class says \"a parcel is an address\", which isn't true, and Java believes it:\n\n- A parcel went into a list of friends' addresses, and nothing stopped it. Any method that takes an Address takes a parcel too.\n- A parcel prints as a bare address. Whatever Address gets later, such as a postcode or a method that formats an envelope, every Parcel gets too, whether it fits or not.\n- A parcel has two addresses: where it goes, and where it comes from, for returns. `extends` gives it one Address part, and a class can extend only one class.\n\n### The fix: has a\n\nA parcel **has** an address, two in fact. \"Has a\" means an instance variable, as in modules 23 and 24. Module 23's Parcel already did this: it kept its Address in one. Here it keeps two:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Address shop = new Address(\"3 Market Street\", \"Leeds\");\n        Parcel parcel = new Parcel(shop, new Address(\"9 Dock Road\", \"Hull\"), 1800);\n        System.out.println(parcel);\n        System.out.println(parcel.getTo());\n    }\n}\n// ==== Address.java ====\npublic class Address {\n    private String street;\n    private String city;\n\n    public Address(String street, String city) {\n        this.street = street;\n        this.city = city;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    @Override\n    public String toString() {\n        return this.street + \", \" + this.city;\n    }\n}\n// ==== Parcel.java ====\npublic class Parcel {\n    private Address from;\n    private Address to;\n    private int grams;\n\n    public Parcel(Address from, Address to, int grams) {\n        this.from = from;\n        this.to = to;\n        this.grams = grams;\n    }\n\n    public Address getTo() {\n        return this.to;\n    }\n\n    @Override\n    public String toString() {\n        return this.grams + \" g from \" + this.from.getCity() + \" to \" + this.to.getCity();\n    }\n}\n```\n\n```output\n1800 g from Leeds to Hull\n9 Dock Road, Hull\n```\n\nNow a parcel has room for both addresses, it prints as a parcel, and `friends.add(parcel)` no longer compiles: `incompatible types: Parcel cannot be converted to Address`. Parcel uses Address's methods through its variables (`this.to.getCity()`), and offers only the methods that make sense for a parcel. Building a class from objects it holds is called **composition**.\n\n### Is a, and has a\n\nSay the sentence out loud, with \"every\":\n\n- \"Every parcel is a shipment.\" True: `Parcel extends Shipment` fits, if the courier has a class for everything it ships. So do \"every film is a library item\" and \"every knight is an adventurer\".\n- \"Every parcel is an address.\" False. \"A parcel has an address\" is true, so it's an instance variable.\n- \"An account has an owner\", \"an archer has a bow\", \"a playlist has songs\": instance variables, and a list for the songs.\n\nA class can do both. A parcel is a shipment, and it has addresses:\n\n```java\npublic class Parcel extends Shipment {\n    private Address from;\n    private Address to;\n    private int grams;\n    ...\n}\n```\n\nSome rules of thumb:\n\n- Use `extends` only when \"every X is a Y\" is true, and every public method of Y makes sense for an X: an X must work wherever a Y is expected.\n- Wanting another class's methods is not enough of a reason. If you only want to use them, hold an object of that class and call its methods.\n- When in doubt, choose \"has a\". A class can extend only one class, and an object can never change its class. But it can swap an object it holds: an archer can switch to a new bow.\n","task":"Someone wrote `Archer extends Bow`, to give archers a bow's `shoot()` and arrows. But an archer isn't a bow: an archer is an adventurer who has a bow, and can switch to a new one. In `Archer.java`, rewrite Archer so that it extends `Adventurer` and has a `Bow` in a private instance variable:\n\n- a constructor `Archer(String name, Bow bow)`\n- `attack()` overridden: the archer shoots the bow, and it returns 6 if an arrow was shot, or 1 if the bow was out of arrows\n- `switchBow(Bow bow)`, which gives the archer another bow\n\n`Bow.java` and `Adventurer.java` are ready, and `Main.java` already uses the new Archer, so the program won't compile until Archer is rewritten. The check runs:\n\n```java\nArcher lyra = new Archer(\"Lyra\", new Bow(1));\nSystem.out.println(lyra.describe());\nSystem.out.println(lyra.describe());\nlyra.switchBow(new Bow(5));\nSystem.out.println(lyra.describe());\n```\n\nand expects:\n\n```\nLyra attacks for 6\nLyra attacks for 1\nLyra attacks for 6\n```\n","kind":"code","seed":"// ==== Archer.java ====\npublic class Archer extends Bow {\n    private String name;\n\n    public Archer(String name, int arrows) {\n        super(arrows);\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int attack() {\n        if (this.shoot()) {\n            return 6;\n        }\n        return 1;\n    }\n}\n\n// ==== Bow.java ====\npublic class Bow {\n    private int arrows;\n\n    public Bow(int arrows) {\n        this.arrows = arrows;\n    }\n\n    public int getArrows() {\n        return this.arrows;\n    }\n\n    public boolean shoot() {\n        if (this.arrows == 0) {\n            return false;\n        }\n        this.arrows--;\n        return true;\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// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Archer lyra = new Archer(\"Lyra\", new Bow(1));\n        System.out.println(lyra.describe());\n        System.out.println(lyra.describe());\n        lyra.switchBow(new Bow(5));\n        System.out.println(lyra.describe());\n    }\n}\n","solution":"// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    private Bow bow;\n\n    public Archer(String name, Bow bow) {\n        super(name);\n        this.bow = bow;\n    }\n\n    @Override\n    public int attack() {\n        if (this.bow.shoot()) {\n            return 6;\n        }\n        return 1;\n    }\n\n    public void switchBow(Bow bow) {\n        this.bow = bow;\n    }\n}\n\n// ==== Bow.java ====\npublic class Bow {\n    private int arrows;\n\n    public Bow(int arrows) {\n        this.arrows = arrows;\n    }\n\n    public int getArrows() {\n        return this.arrows;\n    }\n\n    public boolean shoot() {\n        if (this.arrows == 0) {\n            return false;\n        }\n        this.arrows--;\n        return true;\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// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Archer lyra = new Archer(\"Lyra\", new Bow(1));\n        System.out.println(lyra.describe());\n        System.out.println(lyra.describe());\n        lyra.switchBow(new Bow(5));\n        System.out.println(lyra.describe());\n    }\n}\n","hints":["The header becomes `public class Archer extends Adventurer`, with one instance variable, `private Bow bow;`. The name belongs to Adventurer now, so the constructor starts with `super(name);` and then keeps the bow.","`attack()` asks the bow: `if (this.bow.shoot()) { return 6; }`, and otherwise returns 1. `switchBow` sets `this.bow` to the new bow. `getName` and `describe` come from Adventurer."],"tests":[{"name":"Test 1","stdin":"","call":"Archer lyra = new Archer(\"Lyra\", new Bow(1));\nSystem.out.println(lyra.describe());\nSystem.out.println(lyra.describe());\nlyra.switchBow(new Bow(5));\nSystem.out.println(lyra.describe());\n","expect":"Lyra attacks for 6\nLyra attacks for 1\nLyra attacks for 6","hidden":false},{"name":"Test 2","stdin":"","call":"Bow bow = new Bow(3);\nAdventurer tam = new Archer(\"Tam\", bow);\nSystem.out.println(tam.attack() + \" \" + tam.attack() + \" \" + bow.getArrows());\nSystem.out.println(tam.getName() + \" \" + tam.attack() + \" \" + tam.attack() + \" \" + bow.getArrows());\n","expect":"6 6 1\nTam 6 1 0","hidden":true},{"name":"Test 3","stdin":"","call":"Archer ivo = new Archer(\"Ivo\", new Bow(0));\nSystem.out.println(ivo.attack());\nBow spare = new Bow(2);\nivo.switchBow(spare);\nivo.attack();\nSystem.out.println(spare.getArrows());\nivo.switchBow(new Bow(0));\nSystem.out.println(ivo.describe() + \", spare left: \" + spare.getArrows());\n","expect":"1\n1\nIvo attacks for 1, spare left: 1","hidden":true}],"require":[{"pattern":"\\bclass\\s+Archer\\s+extends\\s+Adventurer\\b","message":"An archer is an adventurer: `public class Archer extends Adventurer`."},{"pattern":"\\bprivate\\s+Bow\\s+\\w+\\s*;","message":"An archer has a bow: keep it in a private instance variable, `private Bow bow;`."}],"forbid":[{"pattern":"\\bextends\\s+Bow\\b","message":"An archer isn't a bow, so Archer shouldn't extend Bow."}],"more":[{"task":"Two archers of the Archer class you just wrote share one bow. What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Bow longbow = new Bow(3);\n        Adventurer lyra = new Archer(\"Lyra\", longbow);\n        Adventurer tam = new Archer(\"Tam\", longbow);\n        System.out.println(lyra.describe());\n        System.out.println(tam.describe());\n        System.out.println(tam.describe());\n        System.out.println(lyra.describe() + \", \" + longbow.getArrows() + \" arrows left\");\n    }\n}\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    private Bow bow;\n\n    public Archer(String name, Bow bow) {\n        super(name);\n        this.bow = bow;\n    }\n\n    @Override\n    public int attack() {\n        if (this.bow.shoot()) {\n            return 6;\n        }\n        return 1;\n    }\n\n    public void switchBow(Bow bow) {\n        this.bow = bow;\n    }\n}\n// ==== Bow.java ====\npublic class Bow {\n    private int arrows;\n\n    public Bow(int arrows) {\n        this.arrows = arrows;\n    }\n\n    public int getArrows() {\n        return this.arrows;\n    }\n\n    public boolean shoot() {\n        if (this.arrows == 0) {\n            return false;\n        }\n        this.arrows--;\n        return true;\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","solution":"public class Main {\n    public static void main(String[] args) {\n        Bow longbow = new Bow(3);\n        Adventurer lyra = new Archer(\"Lyra\", longbow);\n        Adventurer tam = new Archer(\"Tam\", longbow);\n        System.out.println(lyra.describe());\n        System.out.println(tam.describe());\n        System.out.println(tam.describe());\n        System.out.println(lyra.describe() + \", \" + longbow.getArrows() + \" arrows left\");\n    }\n}\n// ==== Archer.java ====\npublic class Archer extends Adventurer {\n    private Bow bow;\n\n    public Archer(String name, Bow bow) {\n        super(name);\n        this.bow = bow;\n    }\n\n    @Override\n    public int attack() {\n        if (this.bow.shoot()) {\n            return 6;\n        }\n        return 1;\n    }\n\n    public void switchBow(Bow bow) {\n        this.bow = bow;\n    }\n}\n// ==== Bow.java ====\npublic class Bow {\n    private int arrows;\n\n    public Bow(int arrows) {\n        this.arrows = arrows;\n    }\n\n    public int getArrows() {\n        return this.arrows;\n    }\n\n    public boolean shoot() {\n        if (this.arrows == 0) {\n            return false;\n        }\n        this.arrows--;\n        return true;\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","hints":["`lyra` and `tam` are Archers, so `describe` calls Archer's `attack`, which shoots the bow. Both archers hold a reference to the same Bow object (module 22), not copies of it.","The bow has 3 arrows in all: every shot by either archer takes one. Once they're gone, an attack gives 1."],"tests":[{"name":"Output","stdin":"","expect":"Lyra attacks for 6\nTam attacks for 6\nTam attacks for 6\nLyra attacks for 1, 0 arrows left","hidden":false}],"require":[],"forbid":[],"lines":["Lyra attacks for 6","Tam attacks for 6","Tam attacks for 6","Lyra attacks for 1, 0 arrows left"]},{"task":"Now the courier's classes, done right. `Shipment` has a tracking code and a base `price()` of 2 dollars, and `Address` is the lesson's. In `Parcel.java`, write the class `Parcel`: a parcel is a shipment, and it has an address to go to. It needs:\n\n- a constructor `Parcel(String code, Address to, int grams)`\n- `price()` overridden: Shipment's price plus 1 dollar for every full 500 grams. Use `super.price()`.\n- `getTo()`, which returns the address\n- `toString()` overridden to return the code, ` to ` and the city of the address\n\nThe check runs:\n\n```java\nParcel parcel = new Parcel(\"P-310\", new Address(\"9 Dock Road\", \"Hull\"), 1800);\nSystem.out.println(parcel);\nSystem.out.println(parcel.price());\nSystem.out.println(parcel.getTo());\nShipment shipment = parcel;\nSystem.out.println(shipment.price());\n```\n\nand expects:\n\n```\nP-310 to Hull\n5\n9 Dock Road, Hull\n5\n```\n","kind":"code","seed":"// ==== Parcel.java ====\npublic class Parcel {\n\n}\n\n// ==== Shipment.java ====\npublic 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 int price() {\n        return 2;\n    }\n}\n\n// ==== Address.java ====\npublic class Address {\n    private String street;\n    private String city;\n\n    public Address(String street, String city) {\n        this.street = street;\n        this.city = city;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    @Override\n    public String toString() {\n        return this.street + \", \" + this.city;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Parcel parcel = new Parcel(\"P-310\", new Address(\"9 Dock Road\", \"Hull\"), 1800);\n        System.out.println(parcel);\n        System.out.println(parcel.price());\n        System.out.println(parcel.getTo());\n        Shipment shipment = parcel;\n        System.out.println(shipment.price());\n    }\n}\n","solution":"// ==== Parcel.java ====\npublic class Parcel extends Shipment {\n    private Address to;\n    private int grams;\n\n    public Parcel(String code, Address to, int grams) {\n        super(code);\n        this.to = to;\n        this.grams = grams;\n    }\n\n    @Override\n    public int price() {\n        return super.price() + this.grams / 500;\n    }\n\n    public Address getTo() {\n        return this.to;\n    }\n\n    @Override\n    public String toString() {\n        return this.getCode() + \" to \" + this.to.getCity();\n    }\n}\n\n// ==== Shipment.java ====\npublic 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 int price() {\n        return 2;\n    }\n}\n\n// ==== Address.java ====\npublic class Address {\n    private String street;\n    private String city;\n\n    public Address(String street, String city) {\n        this.street = street;\n        this.city = city;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    @Override\n    public String toString() {\n        return this.street + \", \" + this.city;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Parcel parcel = new Parcel(\"P-310\", new Address(\"9 Dock Road\", \"Hull\"), 1800);\n        System.out.println(parcel);\n        System.out.println(parcel.price());\n        System.out.println(parcel.getTo());\n        Shipment shipment = parcel;\n        System.out.println(shipment.price());\n    }\n}\n","hints":["`public class Parcel extends Shipment`, with `private Address to;` and `private int grams;`. The constructor hands the code to Shipment with `super(code);`.","`price()` returns `super.price() + this.grams / 500`: int division counts the full 500 grams. `toString()` returns `this.getCode() + \" to \" + this.to.getCity()`, since the code is private to Shipment."],"tests":[{"name":"Test 1","stdin":"","call":"Parcel parcel = new Parcel(\"P-310\", new Address(\"9 Dock Road\", \"Hull\"), 1800);\nSystem.out.println(parcel);\nSystem.out.println(parcel.price());\nSystem.out.println(parcel.getTo());\nShipment shipment = parcel;\nSystem.out.println(shipment.price());\n","expect":"P-310 to Hull\n5\n9 Dock Road, Hull\n5","hidden":false},{"name":"Test 2","stdin":"","call":"Parcel light = new Parcel(\"P-1\", new Address(\"1 High Street\", \"Bath\"), 499);\nParcel even = new Parcel(\"P-2\", new Address(\"2 Low Street\", \"Ely\"), 500);\nSystem.out.println(light.price() + \" \" + even.price() + \" \" + light.getCode());\nSystem.out.println(even + \" / \" + even.getTo().getCity());\n","expect":"2 3 P-1\nP-2 to Ely / Ely","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Shipment> van = new ArrayList<>();\nvan.add(new Shipment(\"S-9\"));\nvan.add(new Parcel(\"P-7\", new Address(\"4 Pier Road\", \"Deal\"), 2600));\nint total = 0;\nfor (Shipment item : van) {\n    total += item.price();\n}\nSystem.out.println(total);\n","expect":"9","hidden":true}],"require":[{"pattern":"\\bclass\\s+Parcel\\s+extends\\s+Shipment\\b","message":"A parcel is a shipment: `public class Parcel extends Shipment`."},{"pattern":"\\bprivate\\s+Address\\s+\\w+\\s*;","message":"A parcel has an address: keep it in a private instance variable, `private Address to;`."},{"pattern":"\\bsuper\\s*\\.\\s*price\\s*\\(","message":"Start from Shipment's price, with `super.price()`."}],"forbid":[{"pattern":"\\bextends\\s+Address\\b","message":"A parcel isn't an address, so Parcel shouldn't extend Address."}]}]}