{"id":"object-interaction-inner-object","slug":"object-inside-object","title":"An object inside an object","text":"An instance variable can hold an object too. You've done it all along: an instance variable of type `String` holds a String object. In the same way, its type can be one of your own classes. A parcel has a recipient and a weight, and it goes to an address, which is a thing of its own, with a street, a house number and a city:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Address address = new Address(\"Elm Street\", 12, \"Riverton\");\n        Parcel parcel = new Parcel(\"Amir\", address, 1200);\n        System.out.println(parcel);\n        System.out.println(parcel.isGoingTo(\"Riverton\"));\n        System.out.println(parcel.isGoingTo(\"Lakeside\"));\n    }\n}\n// ==== Parcel.java ====\npublic class Parcel {\n    private String recipient;\n    private Address address;\n    private int grams;\n\n    public Parcel(String recipient, Address address, int grams) {\n        this.recipient = recipient;\n        this.address = address;\n        this.grams = grams;\n    }\n\n    public boolean isGoingTo(String city) {\n        return this.address.getCity().equals(city);\n    }\n\n    public String toString() {\n        return this.recipient + \", \" + this.address + \" (\" + this.grams + \" g)\";\n    }\n}\n// ==== Address.java ====\npublic class Address {\n    private String street;\n    private int number;\n    private String city;\n\n    public Address(String street, int number, String city) {\n        this.street = street;\n        this.number = number;\n        this.city = city;\n    }\n\n    public String getCity() {\n        return this.city;\n    }\n\n    public String toString() {\n        return this.street + \" \" + this.number + \", \" + this.city;\n    }\n}\n```\n\n```output\nAmir, Elm Street 12, Riverton (1200 g)\ntrue\nfalse\n```\n\n- `private Address address;` is an instance variable like the others, and its type is the class `Address`. The constructor stores the Address it's given, just as it stores the name and the weight.\n- In `toString`, joining `this.address` to a String with `+` calls the address's own `toString`. The parcel doesn't need to know how an address is written out: that's the address's job.\n- `isGoingTo` asks the address for its city with `this.address.getCity()`, and then compares the city it gets back with `equals`. Calls can follow each other like this: each one is made on what the one before it returned.\n- A getter can return the inner object. With `public Address getAddress()` in Parcel, `parcel.getAddress().getCity()` asks the parcel for its address, and then the address for its city.\n\nKeeping the address in a class of its own keeps both classes small, and a class for letters or for a delivery route could use the same Address class. If the constructor forgot to set `this.address`, it would stay `null`, and `isGoingTo` would crash with a NullPointerException (module 22).\n\n### Making the inner object in the constructor\n\nThe caller doesn't have to build the inner object. A constructor can make it from the values it's given:\n\n```java\npublic Parcel(String recipient, String street, int number, String city, int grams) {\n    this.recipient = recipient;\n    this.address = new Address(street, number, city);\n    this.grams = grams;\n}\n```\n\nWith this constructor, `new Parcel(\"Amir\", \"Elm Street\", 12, \"Riverton\", 1200)` makes the parcel and its address in one go. Either way, the parcel ends up with an Address object in its instance variable.\n","task":"A sports team has a name and a coach, and `Coach.java` is ready. In `Team.java`, add a private instance variable `coach` of type `Coach`, and change the constructor to `Team(String name, Coach coach)`. Then write the method `isCoachedBy(String coachName)`: it returns `true` when the team's coach has that name. Ask the coach for its name with `getName()`. The check runs:\n\n```java\nCoach rosa = new Coach(\"Rosa\", 12);\nTeam team = new Team(\"Hawks\", rosa);\nSystem.out.println(team.isCoachedBy(\"Rosa\"));\nSystem.out.println(team.isCoachedBy(\"Ken\"));\n```\n\nand expects:\n\n```\ntrue\nfalse\n```\n","kind":"code","seed":"// ==== Team.java ====\npublic class Team {\n    private String name;\n\n    public Team(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n}\n\n// ==== Coach.java ====\npublic class Coach {\n    private String name;\n    private int years;\n\n    public Coach(String name, int years) {\n        this.name = name;\n        this.years = years;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.years + \" years)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Coach rosa = new Coach(\"Rosa\", 12);\n        Team team = new Team(\"Hawks\", rosa);\n        System.out.println(team.isCoachedBy(\"Rosa\"));\n        System.out.println(team.isCoachedBy(\"Ken\"));\n    }\n}\n","solution":"// ==== Team.java ====\npublic class Team {\n    private String name;\n    private Coach coach;\n\n    public Team(String name, Coach coach) {\n        this.name = name;\n        this.coach = coach;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public boolean isCoachedBy(String coachName) {\n        return this.coach.getName().equals(coachName);\n    }\n}\n\n// ==== Coach.java ====\npublic class Coach {\n    private String name;\n    private int years;\n\n    public Coach(String name, int years) {\n        this.name = name;\n        this.years = years;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.years + \" years)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Coach rosa = new Coach(\"Rosa\", 12);\n        Team team = new Team(\"Hawks\", rosa);\n        System.out.println(team.isCoachedBy(\"Rosa\"));\n        System.out.println(team.isCoachedBy(\"Ken\"));\n    }\n}\n","hints":["The new instance variable is declared like the others, with the class as its type: `private Coach coach;`. The constructor gets a second parameter, `Coach coach`, and stores it with `this.coach = coach;`.","`isCoachedBy` asks the coach for its name and compares it with `equals`: `return this.coach.getName().equals(coachName);`."],"tests":[{"name":"Test 1","stdin":"","call":"Coach rosa = new Coach(\"Rosa\", 12);\nTeam team = new Team(\"Hawks\", rosa);\nSystem.out.println(team.isCoachedBy(\"Rosa\"));\nSystem.out.println(team.isCoachedBy(\"Ken\"));\n","expect":"true\nfalse","hidden":false},{"name":"Test 2","stdin":"","call":"Team team = new Team(\"River Otters\", new Coach(\"Ken\", 3));\nString first = \"K\";\nSystem.out.println(team.isCoachedBy(first + \"en\"));\nSystem.out.println(team.isCoachedBy(\"ken\"));\nSystem.out.println(team.getName());\n","expect":"true\nfalse\nRiver Otters","hidden":true},{"name":"Test 3","stdin":"","call":"Coach lou = new Coach(\"Lou\", 25);\nTeam comets = new Team(\"Comets\", lou);\nTeam lynx = new Team(\"Lynx\", new Coach(\"Mo\", 1));\nSystem.out.println(comets.isCoachedBy(\"Lou\") + \" \" + lynx.isCoachedBy(\"Lou\"));\nSystem.out.println(lynx.isCoachedBy(\"Mo\") + \" \" + comets.isCoachedBy(\"Mo\"));\n","expect":"true false\ntrue false","hidden":true}],"require":[{"pattern":"\\bprivate\\s+Coach\\s+coach\\s*;","message":"Keep the coach in a private instance variable: `private Coach coach;`."},{"pattern":"\\bpublic\\s+Team\\s*\\(\\s*String\\s+\\w+\\s*,\\s*Coach\\s+\\w+\\s*\\)","message":"The constructor takes the name and the coach: `public Team(String name, Coach coach)`."},{"pattern":"\\.getName\\s*\\(\\s*\\)","message":"Ask the coach for its name with `getName()`."}],"forbid":[],"more":[{"task":"What does this program print? Follow the Engine object: which variables refer to it?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Engine engine = new Engine(90);\n        Boat boat = new Boat(\"Gull\", engine);\n        System.out.println(boat);\n        boat.getEngine().tune(10);\n        System.out.println(boat);\n        engine.tune(5);\n        System.out.println(boat.getEngine());\n    }\n}\n// ==== Boat.java ====\npublic class Boat {\n    private String name;\n    private Engine engine;\n\n    public Boat(String name, Engine engine) {\n        this.name = name;\n        this.engine = engine;\n    }\n\n    public Engine getEngine() {\n        return this.engine;\n    }\n\n    public String toString() {\n        return this.name + \" with a \" + this.engine + \" engine\";\n    }\n}\n// ==== Engine.java ====\npublic class Engine {\n    private int power;\n\n    public Engine(int power) {\n        this.power = power;\n    }\n\n    public void tune(int extra) {\n        this.power = this.power + extra;\n    }\n\n    public String toString() {\n        return this.power + \" hp\";\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Engine engine = new Engine(90);\n        Boat boat = new Boat(\"Gull\", engine);\n        System.out.println(boat);\n        boat.getEngine().tune(10);\n        System.out.println(boat);\n        engine.tune(5);\n        System.out.println(boat.getEngine());\n    }\n}\n// ==== Boat.java ====\npublic class Boat {\n    private String name;\n    private Engine engine;\n\n    public Boat(String name, Engine engine) {\n        this.name = name;\n        this.engine = engine;\n    }\n\n    public Engine getEngine() {\n        return this.engine;\n    }\n\n    public String toString() {\n        return this.name + \" with a \" + this.engine + \" engine\";\n    }\n}\n// ==== Engine.java ====\npublic class Engine {\n    private int power;\n\n    public Engine(int power) {\n        this.power = power;\n    }\n\n    public void tune(int extra) {\n        this.power = this.power + extra;\n    }\n\n    public String toString() {\n        return this.power + \" hp\";\n    }\n}\n","hints":["`boat.getEngine()` returns the boat's Engine object, and `.tune(10)` is called on it. The boat's engine now has 100 hp.","The constructor stored the same Engine that `engine` in `main` refers to. So `engine.tune(5)` tunes the boat's engine as well, and printing it calls the engine's `toString`."],"tests":[{"name":"Output","stdin":"","expect":"Gull with a 90 hp engine\nGull with a 100 hp engine\n105 hp","hidden":false}],"require":[],"forbid":[],"lines":["Gull with a 90 hp engine","Gull with a 100 hp engine","105 hp"]},{"task":"A train ticket keeps its route in a `Route` object, and `Route.java` is ready. In `Ticket.java`, write:\n\n- the constructor `Ticket(String passenger, String from, String to)`, which stores the passenger and makes the route itself, from `from` and `to`;\n- the method `goesTo(String city)`, which returns `true` when the ticket's route ends in that city. Ask the route where it ends with `getTo()`.\n\nThe check runs:\n\n```java\nTicket ticket = new Ticket(\"Lea\", \"Harbor Town\", \"Hill Park\");\nSystem.out.println(ticket);\nSystem.out.println(ticket.goesTo(\"Hill Park\"));\nSystem.out.println(ticket.goesTo(\"Harbor Town\"));\n```\n\nand expects:\n\n```\nLea: Harbor Town to Hill Park\ntrue\nfalse\n```\n","kind":"code","seed":"// ==== Ticket.java ====\npublic class Ticket {\n    private String passenger;\n    private Route route;\n\n    // Write the constructor and the goesTo method here.\n\n    public String toString() {\n        return this.passenger + \": \" + this.route;\n    }\n}\n\n// ==== Route.java ====\npublic class Route {\n    private String from;\n    private String to;\n\n    public Route(String from, String to) {\n        this.from = from;\n        this.to = to;\n    }\n\n    public String getFrom() {\n        return this.from;\n    }\n\n    public String getTo() {\n        return this.to;\n    }\n\n    public String toString() {\n        return this.from + \" to \" + this.to;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Ticket ticket = new Ticket(\"Lea\", \"Harbor Town\", \"Hill Park\");\n        System.out.println(ticket);\n        System.out.println(ticket.goesTo(\"Hill Park\"));\n        System.out.println(ticket.goesTo(\"Harbor Town\"));\n    }\n}\n","solution":"// ==== Ticket.java ====\npublic class Ticket {\n    private String passenger;\n    private Route route;\n\n    public Ticket(String passenger, String from, String to) {\n        this.passenger = passenger;\n        this.route = new Route(from, to);\n    }\n\n    public boolean goesTo(String city) {\n        return this.route.getTo().equals(city);\n    }\n\n    public String toString() {\n        return this.passenger + \": \" + this.route;\n    }\n}\n\n// ==== Route.java ====\npublic class Route {\n    private String from;\n    private String to;\n\n    public Route(String from, String to) {\n        this.from = from;\n        this.to = to;\n    }\n\n    public String getFrom() {\n        return this.from;\n    }\n\n    public String getTo() {\n        return this.to;\n    }\n\n    public String toString() {\n        return this.from + \" to \" + this.to;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Ticket ticket = new Ticket(\"Lea\", \"Harbor Town\", \"Hill Park\");\n        System.out.println(ticket);\n        System.out.println(ticket.goesTo(\"Hill Park\"));\n        System.out.println(ticket.goesTo(\"Harbor Town\"));\n    }\n}\n","hints":["The constructor gets two city names, not a Route. It makes the Route from them with `new` and stores it in `this.route`. `goesTo` then asks that route where it ends, and compares the answer with the city.","In the constructor: `this.passenger = passenger;` and `this.route = new Route(from, to);`. In `goesTo`: `return this.route.getTo().equals(city);`. Compare text with `equals`, not `==`."],"tests":[{"name":"Test 1","stdin":"","call":"Ticket ticket = new Ticket(\"Lea\", \"Harbor Town\", \"Hill Park\");\nSystem.out.println(ticket);\nSystem.out.println(ticket.goesTo(\"Hill Park\"));\nSystem.out.println(ticket.goesTo(\"Harbor Town\"));\n","expect":"Lea: Harbor Town to Hill Park\ntrue\nfalse","hidden":false},{"name":"Test 2","stdin":"","call":"Ticket ticket = new Ticket(\"Oskar\", \"Mill End\", \"Stone Bay\");\nString first = \"Stone\";\nSystem.out.println(ticket.goesTo(first + \" Bay\"));\nSystem.out.println(ticket.goesTo(\"Mill End\"));\nSystem.out.println(ticket);\n","expect":"true\nfalse\nOskar: Mill End to Stone Bay","hidden":true},{"name":"Test 3","stdin":"","call":"Ticket out = new Ticket(\"Noor\", \"Ash Lane\", \"Oak Hill\");\nTicket back = new Ticket(\"Noor\", \"Oak Hill\", \"Ash Lane\");\nSystem.out.println(back);\nSystem.out.println(out.goesTo(\"Ash Lane\") + \" \" + back.goesTo(\"Ash Lane\"));\n","expect":"Noor: Oak Hill to Ash Lane\nfalse true","hidden":true}],"require":[{"pattern":"\\bnew\\s+Route\\s*\\(","message":"Make the route in the constructor with `new Route(from, to)`."},{"pattern":"\\.getTo\\s*\\(\\s*\\)","message":"Ask the route where it ends with `getTo()`."}],"forbid":[]}]}