{"id":"object-methods-tostring","slug":"tostring","title":"toString","text":"### Printing an object\n\nTo show a plant, the `Plant` of module 17 had a method `printInfo()`. It works, but the text can only go straight to the screen, on a line of its own: it can't be part of a longer line, or be stored in a variable. What about printing the object itself, with `System.out.println(basil)`? It compiles, but for a class like `Plant` it prints the class name, an `@` and a code of letters and digits, something like `Plant@1b6d3586`. The code is an internal number that means nothing to a reader, and it may differ between runs and between computers. That's why no check in this course ever shows it.\n\n### toString\n\nA class decides how its objects look as text with a method called `toString`. It has no parameters and returns a String:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Ferry ferry = new Ferry(\"Aurora\");\n        System.out.println(ferry);\n        ferry.board(12);\n        System.out.println(ferry);\n        String line = \"Departing: \" + ferry;\n        System.out.println(line);\n    }\n}\n// ==== Ferry.java ====\npublic class Ferry {\n    private String name;\n    private int cars;\n\n    public Ferry(String name) {\n        this.name = name;\n        this.cars = 0;\n    }\n\n    public void board(int count) {\n        this.cars = this.cars + count;\n    }\n\n    public String toString() {\n        return \"Ferry \" + this.name + \", \" + this.cars + \" cars on board\";\n    }\n}\n```\n\n```output\nFerry Aurora, 0 cars on board\nFerry Aurora, 12 cars on board\nDeparting: Ferry Aurora, 12 cars on board\n```\n\n- The header must be exactly `public String toString()`. With another name, or with a parameter, `println` won't use it.\n- `System.out.println(ferry)` calls `ferry.toString()` for you and prints the text it returns.\n- Joining an object to a String with `+` calls it too: `\"Departing: \" + ferry` is `\"Departing: \"` followed by what `toString` returns.\n- The text is built each time the method is called, from the object's variables at that moment. After `board(12)` it shows the new number of cars.\n\n`toString` **returns** the text; it doesn't print it. Printing is up to the code that calls it, so the same text can be printed, stored in a variable or joined into a longer line. Like any method that returns a String, `toString` can use `if` and build its text in steps.\n","task":"Add a `toString` to the `Guitar` class, so a guitar prints as its model, with its number of strings in parentheses. The check creates `new Guitar(\"Lark\", 6)` and prints it:\n\n```\nLark (6 strings)\n```\n","kind":"code","seed":"// ==== Guitar.java ====\npublic class Guitar {\n    private String model;\n    private int strings;\n\n    public Guitar(String model, int strings) {\n        this.model = model;\n        this.strings = strings;\n    }\n\n    // Write the toString method here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Guitar guitar = new Guitar(\"Lark\", 6);\n        System.out.println(guitar);\n    }\n}\n","solution":"// ==== Guitar.java ====\npublic class Guitar {\n    private String model;\n    private int strings;\n\n    public Guitar(String model, int strings) {\n        this.model = model;\n        this.strings = strings;\n    }\n\n    public String toString() {\n        return this.model + \" (\" + this.strings + \" strings)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Guitar guitar = new Guitar(\"Lark\", 6);\n        System.out.println(guitar);\n    }\n}\n","hints":["The header is `public String toString() {`, and the method returns the text instead of printing it.","`return this.model + \" (\" + this.strings + \" strings)\";`"],"tests":[{"name":"Test 1","stdin":"","call":"Guitar guitar = new Guitar(\"Lark\", 6);\nSystem.out.println(guitar);\n","expect":"Lark (6 strings)","hidden":false},{"name":"Test 2","stdin":"","call":"Guitar guitar = new Guitar(\"Cedar\", 12);\nSystem.out.println(\"My guitar: \" + guitar);\n","expect":"My guitar: Cedar (12 strings)","hidden":true},{"name":"Test 3","stdin":"","call":"Guitar first = new Guitar(\"Mira\", 7);\nGuitar second = new Guitar(\"Basso\", 4);\nSystem.out.println(first);\nSystem.out.println(second.toString());\n","expect":"Mira (7 strings)\nBasso (4 strings)","hidden":true}],"require":[{"pattern":"\\bpublic\\s+String\\s+toString\\s*\\(\\s*\\)","message":"Write the method as `public String toString()`, so `println` uses it."}],"forbid":[],"more":[{"task":"A `Chore` on a to-do list is either done or not. Add a `toString` that returns `[ ] ` followed by the chore's title while it's not done, and `[x] ` followed by the title once it's done. The check prints a new chore, marks it done and prints it again:\n\n```\n[ ] Water the plants\n[x] Water the plants\n```\n","kind":"code","seed":"// ==== Chore.java ====\npublic class Chore {\n    private String title;\n    private boolean done;\n\n    public Chore(String title) {\n        this.title = title;\n        this.done = false;\n    }\n\n    public void markDone() {\n        this.done = true;\n    }\n\n    // Write the toString method here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Chore chore = new Chore(\"Water the plants\");\n        System.out.println(chore);\n        chore.markDone();\n        System.out.println(chore);\n    }\n}\n","solution":"// ==== Chore.java ====\npublic class Chore {\n    private String title;\n    private boolean done;\n\n    public Chore(String title) {\n        this.title = title;\n        this.done = false;\n    }\n\n    public void markDone() {\n        this.done = true;\n    }\n\n    public String toString() {\n        if (this.done) {\n            return \"[x] \" + this.title;\n        }\n        return \"[ ] \" + this.title;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Chore chore = new Chore(\"Water the plants\");\n        System.out.println(chore);\n        chore.markDone();\n        System.out.println(chore);\n    }\n}\n","hints":["Return one text when `this.done` is true and another when it's false: an `if` with a `return`, and a `return` after it.","`if (this.done) { return \"[x] \" + this.title; }`, and after it `return \"[ ] \" + this.title;`"],"tests":[{"name":"Test 1","stdin":"","call":"Chore chore = new Chore(\"Water the plants\");\nSystem.out.println(chore);\nchore.markDone();\nSystem.out.println(chore);\n","expect":"[ ] Water the plants\n[x] Water the plants","hidden":false},{"name":"Test 2","stdin":"","call":"Chore dishes = new Chore(\"Dishes\");\nChore trash = new Chore(\"Take out the trash\");\ntrash.markDone();\nSystem.out.println(dishes);\nSystem.out.println(trash);\n","expect":"[ ] Dishes\n[x] Take out the trash","hidden":true},{"name":"Test 3","stdin":"","call":"Chore chore = new Chore(\"Call grandma\");\nchore.markDone();\nchore.markDone();\nSystem.out.println(\"Today: \" + chore);\n","expect":"Today: [x] Call grandma","hidden":true}],"require":[{"pattern":"\\bpublic\\s+String\\s+toString\\s*\\(\\s*\\)","message":"Write the method as `public String toString()`, so `println` uses it."}],"forbid":[]},{"task":"What does this program print? Watch when each `toString` call happens.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Oven oven = new Oven();\n        System.out.println(oven);\n        oven.heat(100);\n        oven.heat(80);\n        String note = \"Was at \" + oven;\n        oven.turnOff();\n        System.out.println(note);\n        System.out.println(\"Now \" + oven);\n    }\n}\n// ==== Oven.java ====\npublic class Oven {\n    private int degrees;\n\n    public Oven() {\n        this.degrees = 0;\n    }\n\n    public void heat(int amount) {\n        this.degrees = this.degrees + amount;\n    }\n\n    public void turnOff() {\n        this.degrees = 0;\n    }\n\n    public String toString() {\n        if (this.degrees == 0) {\n            return \"off\";\n        }\n        return this.degrees + \" degrees\";\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Oven oven = new Oven();\n        System.out.println(oven);\n        oven.heat(100);\n        oven.heat(80);\n        String note = \"Was at \" + oven;\n        oven.turnOff();\n        System.out.println(note);\n        System.out.println(\"Now \" + oven);\n    }\n}\n// ==== Oven.java ====\npublic class Oven {\n    private int degrees;\n\n    public Oven() {\n        this.degrees = 0;\n    }\n\n    public void heat(int amount) {\n        this.degrees = this.degrees + amount;\n    }\n\n    public void turnOff() {\n        this.degrees = 0;\n    }\n\n    public String toString() {\n        if (this.degrees == 0) {\n            return \"off\";\n        }\n        return this.degrees + \" degrees\";\n    }\n}\n","hints":["`\"Was at \" + oven` calls `toString` right there, while the oven is at 180 degrees. The String stored in `note` doesn't change when the oven does.","The first line is printed before any heating, and the last one after `turnOff()`: both times `toString` returns `off`."],"tests":[{"name":"Output","stdin":"","expect":"off\nWas at 180 degrees\nNow off","hidden":false}],"require":[],"forbid":[],"lines":["off","Was at 180 degrees","Now off"]}]}