{"id":"classes-changing-state","slug":"changing-an-object","title":"Changing an object","text":"An object remembers. Its instance variables keep their values from one method call to the next, and a method can change them. The values an object holds at a given moment are its **state**. Here the plant gets two methods that change its height:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Plant ivy = new Plant(\"ivy\", 40);\n        ivy.printInfo();\n        ivy.grow(15);\n        ivy.printInfo();\n        ivy.cut(30);\n        ivy.printInfo();\n        ivy.cut(50);\n        ivy.printInfo();\n    }\n}\n// ==== Plant.java ====\npublic class Plant {\n    private String name;\n    private int height;\n\n    public Plant(String name, int height) {\n        this.name = name;\n        this.height = height;\n    }\n\n    public void printInfo() {\n        System.out.println(this.name + \", \" + this.height + \" cm\");\n    }\n\n    public void grow(int cm) {\n        this.height = this.height + cm;\n    }\n\n    public void cut(int cm) {\n        this.height = this.height - cm;\n        if (this.height < 5) {\n            this.height = 5;\n        }\n    }\n}\n```\n\n```output\nivy, 40 cm\nivy, 55 cm\nivy, 25 cm\nivy, 5 cm\n```\n\n- `this.height = this.height + cm;` changes the object's own height. After `ivy.grow(15)` it stays 55 until another call changes it, and the next `printInfo()` prints the new value. (`this.height += cm;` does the same.)\n- `cut` has a condition. The gardener always leaves at least 5 cm, so a plant never gets shorter than that: `ivy.cut(50)` would take the height to -25, and the `if` puts it back up to 5.\n- Some methods change the state, like `grow` and `cut`. Others only look at it, like `printInfo`.\n\nA method that changes the state doesn't need a parameter. The lamp's `turnOn()` from step 1 simply sets `this.on = true;`.\n","task":"The `WaterBottle` from step 3 comes full and has a `printInfo()` method. Add a method `drink(int amount)` that takes `amount` milliliters out of the bottle. A bottle can't hold less than nothing: when the amount is more than what's left, the bottle becomes empty (0 ml). The check runs:\n\n```java\nWaterBottle bottle = new WaterBottle(750);\nbottle.drink(200);\nbottle.printInfo();\nbottle.drink(600);\nbottle.printInfo();\n```\n\nand expects:\n\n```\n550/750 ml\n0/750 ml\n```\n","kind":"code","seed":"// ==== WaterBottle.java ====\npublic class WaterBottle {\n    private int capacity;\n    private int milliliters;\n\n    public WaterBottle(int capacity) {\n        this.capacity = capacity;\n        this.milliliters = capacity;\n    }\n\n    // Write the drink method here.\n\n    public void printInfo() {\n        System.out.println(this.milliliters + \"/\" + this.capacity + \" ml\");\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        WaterBottle bottle = new WaterBottle(750);\n        bottle.drink(200);\n        bottle.printInfo();\n        bottle.drink(600);\n        bottle.printInfo();\n    }\n}\n","solution":"// ==== WaterBottle.java ====\npublic class WaterBottle {\n    private int capacity;\n    private int milliliters;\n\n    public WaterBottle(int capacity) {\n        this.capacity = capacity;\n        this.milliliters = capacity;\n    }\n\n    public void drink(int amount) {\n        this.milliliters = this.milliliters - amount;\n        if (this.milliliters < 0) {\n            this.milliliters = 0;\n        }\n    }\n\n    public void printInfo() {\n        System.out.println(this.milliliters + \"/\" + this.capacity + \" ml\");\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        WaterBottle bottle = new WaterBottle(750);\n        bottle.drink(200);\n        bottle.printInfo();\n        bottle.drink(600);\n        bottle.printInfo();\n    }\n}\n","hints":["`drink` changes the bottle's own variable: `this.milliliters = this.milliliters - amount;`.","Then, like `cut` in the example, an `if` sets it to 0 when it went below 0."],"tests":[{"name":"Test 1","stdin":"","call":"WaterBottle bottle = new WaterBottle(750);\nbottle.drink(200);\nbottle.printInfo();\nbottle.drink(600);\nbottle.printInfo();\n","expect":"550/750 ml\n0/750 ml","hidden":false},{"name":"Test 2","stdin":"","call":"WaterBottle bottle = new WaterBottle(500);\nbottle.drink(500);\nbottle.printInfo();\nbottle.drink(0);\nbottle.printInfo();\n","expect":"0/500 ml\n0/500 ml","hidden":true},{"name":"Test 3","stdin":"","call":"WaterBottle bottle = new WaterBottle(1000);\nbottle.drink(100);\nbottle.drink(100);\nbottle.drink(100);\nbottle.printInfo();\nbottle.drink(800);\nbottle.printInfo();\n","expect":"700/1000 ml\n0/1000 ml","hidden":true}],"require":[],"forbid":[],"more":[{"task":"A `TrafficLight` shows `red`, `green` or `yellow`. Its constructor, which has no parameters, starts it at red. Write the method `next()`, which moves the light on: red turns green, green turns yellow, and yellow turns red again. The check runs:\n\n```java\nTrafficLight light = new TrafficLight();\nlight.printColor();\nlight.next();\nlight.printColor();\nlight.next();\nlight.printColor();\n```\n\nand expects:\n\n```\nred\ngreen\nyellow\n```\n","kind":"code","seed":"// ==== TrafficLight.java ====\npublic class TrafficLight {\n    private String color;\n\n    public TrafficLight() {\n        this.color = \"red\";\n    }\n\n    // Write the next method here.\n\n    public void printColor() {\n        System.out.println(this.color);\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        TrafficLight light = new TrafficLight();\n        light.printColor();\n        light.next();\n        light.printColor();\n        light.next();\n        light.printColor();\n    }\n}\n","solution":"// ==== TrafficLight.java ====\npublic class TrafficLight {\n    private String color;\n\n    public TrafficLight() {\n        this.color = \"red\";\n    }\n\n    public void next() {\n        if (this.color.equals(\"red\")) {\n            this.color = \"green\";\n        } else if (this.color.equals(\"green\")) {\n            this.color = \"yellow\";\n        } else {\n            this.color = \"red\";\n        }\n    }\n\n    public void printColor() {\n        System.out.println(this.color);\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        TrafficLight light = new TrafficLight();\n        light.printColor();\n        light.next();\n        light.printColor();\n        light.next();\n        light.printColor();\n    }\n}\n","hints":["Compare the current color with `equals`, then set the next one: `if (this.color.equals(\"red\")) { this.color = \"green\"; }`.","Use `else if` and `else`, so that one call changes the color only once. With three separate `if`s, a single call would go all the way round: the first `if` turns red into green, the second turns that green into yellow, and the third turns the yellow back into red."],"tests":[{"name":"Test 1","stdin":"","call":"TrafficLight light = new TrafficLight();\nlight.printColor();\nlight.next();\nlight.printColor();\nlight.next();\nlight.printColor();\n","expect":"red\ngreen\nyellow","hidden":false},{"name":"Test 2","stdin":"","call":"TrafficLight light = new TrafficLight();\nlight.next();\nlight.next();\nlight.next();\nlight.printColor();\nlight.next();\nlight.printColor();\n","expect":"red\ngreen","hidden":true},{"name":"Test 3","stdin":"","call":"TrafficLight north = new TrafficLight();\nTrafficLight east = new TrafficLight();\neast.next();\neast.next();\nnorth.printColor();\neast.printColor();\n","expect":"red\nyellow","hidden":true}],"require":[],"forbid":[{"pattern":"(==|!=)\\s*\"\"|\"\"\\s*(==|!=)","message":"Compare text with `equals`, not `==`."}]},{"task":"What does this program print? The elevator remembers its floor between the calls.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Elevator lift = new Elevator(4);\n        lift.ride(3);\n        lift.printFloor();\n        lift.ride(5);\n        lift.printFloor();\n        lift.ride(-6);\n        lift.printFloor();\n    }\n}\n// ==== Elevator.java ====\npublic class Elevator {\n    private int floor;\n    private int topFloor;\n\n    public Elevator(int topFloor) {\n        this.floor = 0;\n        this.topFloor = topFloor;\n    }\n\n    public void ride(int floors) {\n        this.floor = this.floor + floors;\n        if (this.floor > this.topFloor) {\n            this.floor = this.topFloor;\n        }\n        if (this.floor < 0) {\n            this.floor = 0;\n        }\n    }\n\n    public void printFloor() {\n        System.out.println(\"Floor \" + this.floor);\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Elevator lift = new Elevator(4);\n        lift.ride(3);\n        lift.printFloor();\n        lift.ride(5);\n        lift.printFloor();\n        lift.ride(-6);\n        lift.printFloor();\n    }\n}\n// ==== Elevator.java ====\npublic class Elevator {\n    private int floor;\n    private int topFloor;\n\n    public Elevator(int topFloor) {\n        this.floor = 0;\n        this.topFloor = topFloor;\n    }\n\n    public void ride(int floors) {\n        this.floor = this.floor + floors;\n        if (this.floor > this.topFloor) {\n            this.floor = this.topFloor;\n        }\n        if (this.floor < 0) {\n            this.floor = 0;\n        }\n    }\n\n    public void printFloor() {\n        System.out.println(\"Floor \" + this.floor);\n    }\n}\n","hints":["The elevator starts at floor 0, and its top floor is 4. `ride(3)` takes it to floor 3.","`ride(5)` would go to 8, but the first `if` stops it at the top floor. From there, `ride(-6)` would go below 0, and the second `if` stops it at 0."],"tests":[{"name":"Output","stdin":"","expect":"Floor 3\nFloor 4\nFloor 0","hidden":false}],"require":[],"forbid":[],"lines":["Floor 3","Floor 4","Floor 0"]}]}