{"id":"object-methods-this","slug":"this-and-parameters","title":"Parameters and this","text":"Module 17's constructors all used lines like `this.name = name;`, where `this.name` is the object's variable and `name` the parameter. The point behind it: a parameter with the same name as an instance variable **hides** that variable. Inside the constructor or method, a plain `name` always means the parameter, and `this.name` is the only way to reach the object's own variable.\n\n### Without this\n\nLeave out `this.`, and both sides of `name = name;` mean the parameter. The line copies the parameter into itself, and the instance variable is never set. It keeps the value every instance variable starts with: 0 for a number, `false` for a boolean, and `null` for a String, which means *no String at all*:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Guest guest = new Guest(\"Amara\", 3);\n        System.out.println(guest);\n    }\n}\n// ==== Guest.java ====\npublic class Guest {\n    private String name;\n    private int nights;\n\n    public Guest(String name, int nights) {\n        name = name;\n        nights = nights;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.nights + \" nights\";\n    }\n}\n```\n\n```output\nnull, 0 nights\n```\n\nJava doesn't complain: `name = name;` is allowed, it just does nothing useful. When an object shows `null` or 0 where you expected a value, a missing `this.` is the first thing to look for.\n\n### Methods with parameters\n\nThe same goes for every method whose parameter has the name of an instance variable. Methods that change an object often get the new value as a parameter:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Guest guest = new Guest(\"Amara\", 3);\n        guest.extend(2);\n        guest.rename(\"Amara Obi\");\n        System.out.println(guest);\n    }\n}\n// ==== Guest.java ====\npublic class Guest {\n    private String name;\n    private int nights;\n\n    public Guest(String name, int nights) {\n        this.name = name;\n        this.nights = nights;\n    }\n\n    public void extend(int nights) {\n        this.nights = this.nights + nights;\n    }\n\n    public void rename(String newName) {\n        name = newName;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.nights + \" nights\";\n    }\n}\n```\n\n```output\nAmara Obi, 5 nights\n```\n\n- In `extend`, `this.nights` is the guest's nights so far, and `nights` is the parameter: the nights to add.\n- In `rename` the parameter has another name, so `name` can only mean the instance variable, and `this.` isn't needed. Many programmers write it anyway, and so does this course: with `this.` in front, it's always clear which variables belong to the object.\n","task":"This program should print `Pancakes (20 min)`, but it prints `null (0 min)`. Fix the constructor of `Recipe`. The check creates `new Recipe(\"Pancakes\", 20)` and prints it:\n\n```\nPancakes (20 min)\n```\n","kind":"code","seed":"// ==== Recipe.java ====\npublic class Recipe {\n    private String name;\n    private int minutes;\n\n    public Recipe(String name, int minutes) {\n        name = name;\n        minutes = minutes;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.minutes + \" min)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Recipe recipe = new Recipe(\"Pancakes\", 20);\n        System.out.println(recipe);\n    }\n}\n","solution":"// ==== Recipe.java ====\npublic class Recipe {\n    private String name;\n    private int minutes;\n\n    public Recipe(String name, int minutes) {\n        this.name = name;\n        this.minutes = minutes;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.minutes + \" min)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Recipe recipe = new Recipe(\"Pancakes\", 20);\n        System.out.println(recipe);\n    }\n}\n","hints":["In `name = name;` both names mean the parameter, so the object's own `name` is never set.","Write `this.` in front of the instance variables: `this.name = name;` and `this.minutes = minutes;`"],"tests":[{"name":"Test 1","stdin":"","call":"Recipe recipe = new Recipe(\"Pancakes\", 20);\nSystem.out.println(recipe);\n","expect":"Pancakes (20 min)","hidden":false},{"name":"Test 2","stdin":"","call":"Recipe soup = new Recipe(\"Lentil soup\", 45);\nRecipe salad = new Recipe(\"Salad\", 10);\nSystem.out.println(soup);\nSystem.out.println(salad);\n","expect":"Lentil soup (45 min)\nSalad (10 min)","hidden":true}],"require":[],"forbid":[],"more":[{"task":"The volume of a `Speaker` goes from 0 to 10. Add a method `setLevel(int level)` that sets the volume. A level above 10 sets it to 10, and a level below 0 sets it to 0. The check sets the levels 7, 15 and -2, and prints the volume after each:\n\n```\n7\n10\n0\n```\n","kind":"code","seed":"// ==== Speaker.java ====\npublic class Speaker {\n    private int level;\n\n    public Speaker() {\n        this.level = 3;\n    }\n\n    public int getLevel() {\n        return this.level;\n    }\n\n    // Write the setLevel method here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Speaker speaker = new Speaker();\n        speaker.setLevel(7);\n        System.out.println(\"Volume: \" + speaker.getLevel());\n    }\n}\n","solution":"// ==== Speaker.java ====\npublic class Speaker {\n    private int level;\n\n    public Speaker() {\n        this.level = 3;\n    }\n\n    public int getLevel() {\n        return this.level;\n    }\n\n    public void setLevel(int level) {\n        if (level > 10) {\n            this.level = 10;\n        } else if (level < 0) {\n            this.level = 0;\n        } else {\n            this.level = level;\n        }\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Speaker speaker = new Speaker();\n        speaker.setLevel(7);\n        System.out.println(\"Volume: \" + speaker.getLevel());\n    }\n}\n","hints":["The parameter is called `level`, like the instance variable, so the object's own one is `this.level`.","Check the limits first: `if (level > 10) { this.level = 10; } else if (level < 0) { this.level = 0; } else { this.level = level; }`"],"tests":[{"name":"Test 1","stdin":"","call":"Speaker speaker = new Speaker();\nspeaker.setLevel(7);\nSystem.out.println(speaker.getLevel());\nspeaker.setLevel(15);\nSystem.out.println(speaker.getLevel());\nspeaker.setLevel(-2);\nSystem.out.println(speaker.getLevel());\n","expect":"7\n10\n0","hidden":false},{"name":"Test 2","stdin":"","call":"Speaker speaker = new Speaker();\nspeaker.setLevel(10);\nSystem.out.println(speaker.getLevel());\nspeaker.setLevel(0);\nSystem.out.println(speaker.getLevel());\nspeaker.setLevel(1);\nSystem.out.println(speaker.getLevel());\n","expect":"10\n0\n1","hidden":true},{"name":"Test 3","stdin":"","call":"Speaker kitchen = new Speaker();\nSpeaker garden = new Speaker();\ngarden.setLevel(9);\nSystem.out.println(kitchen.getLevel());\nSystem.out.println(garden.getLevel());\n","expect":"3\n9","hidden":true}],"require":[],"forbid":[]},{"task":"What does this program print? Look closely at which variables each method changes.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Badge badge = new Badge(\"Mia\");\n        badge.rename(\"Zoe\");\n        System.out.println(badge);\n        badge.levelUp(2);\n        badge.rename(\"Ola\");\n        System.out.println(badge);\n    }\n}\n// ==== Badge.java ====\npublic class Badge {\n    private String name;\n    private int level;\n\n    public Badge(String name) {\n        this.name = name;\n        this.level = 1;\n    }\n\n    public void rename(String name) {\n        name = name.toUpperCase();\n    }\n\n    public void levelUp(int levels) {\n        this.level = this.level + levels;\n    }\n\n    public String toString() {\n        return this.name + \" (level \" + this.level + \")\";\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Badge badge = new Badge(\"Mia\");\n        badge.rename(\"Zoe\");\n        System.out.println(badge);\n        badge.levelUp(2);\n        badge.rename(\"Ola\");\n        System.out.println(badge);\n    }\n}\n// ==== Badge.java ====\npublic class Badge {\n    private String name;\n    private int level;\n\n    public Badge(String name) {\n        this.name = name;\n        this.level = 1;\n    }\n\n    public void rename(String name) {\n        name = name.toUpperCase();\n    }\n\n    public void levelUp(int levels) {\n        this.level = this.level + levels;\n    }\n\n    public String toString() {\n        return this.name + \" (level \" + this.level + \")\";\n    }\n}\n","hints":["In `rename`, both `name`s are the parameter: the method changes only its own copy, so the badge keeps the name `Mia`.","`levelUp` uses `this.level`, so it does change the badge: 1 + 2 is 3."],"tests":[{"name":"Output","stdin":"","expect":"Mia (level 1)\nMia (level 3)","hidden":false}],"require":[],"forbid":[],"lines":["Mia (level 1)","Mia (level 3)"]}]}