{"id":"object-methods-internal-calls","slug":"calling-own-methods","title":"Calling the object's own methods","text":"A method can call the other methods of its own object. Inside the class, `this.isFull()` calls `isFull` on the same object the current method was called on. This bus uses that:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Bus bus = new Bus(2);\n        bus.board();\n        System.out.println(bus);\n        bus.board();\n        bus.board();\n        System.out.println(bus);\n    }\n}\n// ==== Bus.java ====\npublic class Bus {\n    private int seats;\n    private int passengers;\n\n    public Bus(int seats) {\n        this.seats = seats;\n        this.passengers = 0;\n    }\n\n    public int seatsLeft() {\n        return this.seats - this.passengers;\n    }\n\n    public boolean isFull() {\n        return this.seatsLeft() == 0;\n    }\n\n    public void board() {\n        if (this.isFull()) {\n            System.out.println(\"Sorry, the bus is full\");\n        } else {\n            this.passengers++;\n        }\n    }\n\n    public String toString() {\n        return this.passengers + \" on board, seats left: \" + this.seatsLeft();\n    }\n}\n```\n\n```output\n1 on board, seats left: 1\nSorry, the bus is full\n2 on board, seats left: 0\n```\n\n- `seatsLeft()` works out the free seats. `isFull()` asks `seatsLeft()` instead of doing the sum again, and `board()` asks `isFull()` before it lets anyone on.\n- Each rule is written in one place. If the bus took standing passengers one day, only `seatsLeft` would change, and `isFull`, `board` and `toString` would all follow.\n- `this.` in front of the call can be left out: inside the class, `isFull()` means the same. As with instance variables, writing it shows that the method belongs to this object.\n\nA method that only the class itself needs can be `private`, like the instance variables. If nothing outside the bus used `seatsLeft`, it could be `private int seatsLeft()`: `isFull` and `toString` could still call it, but `main` couldn't.\n","task":"A `Flashlight` knows the charge of its battery in percent, and `isLow()` tells whether it's below 20. Add a `toString` that returns the charge with a `%` sign, followed by ` (low)` when the charge is low. Use `isLow()` for that, instead of comparing the charge again. The check prints a flashlight at 30 percent, uses 15 and prints it again:\n\n```\n30%\n15% (low)\n```\n","kind":"code","seed":"// ==== Flashlight.java ====\npublic class Flashlight {\n    private int charge;\n\n    public Flashlight(int charge) {\n        this.charge = charge;\n    }\n\n    public void use(int amount) {\n        this.charge = this.charge - amount;\n    }\n\n    public boolean isLow() {\n        return this.charge < 20;\n    }\n\n    // Write the toString method here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Flashlight light = new Flashlight(30);\n        System.out.println(light);\n        light.use(15);\n        System.out.println(light);\n    }\n}\n","solution":"// ==== Flashlight.java ====\npublic class Flashlight {\n    private int charge;\n\n    public Flashlight(int charge) {\n        this.charge = charge;\n    }\n\n    public void use(int amount) {\n        this.charge = this.charge - amount;\n    }\n\n    public boolean isLow() {\n        return this.charge < 20;\n    }\n\n    public String toString() {\n        if (this.isLow()) {\n            return this.charge + \"% (low)\";\n        }\n        return this.charge + \"%\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Flashlight light = new Flashlight(30);\n        System.out.println(light);\n        light.use(15);\n        System.out.println(light);\n    }\n}\n","hints":["Inside the class, `this.isLow()` calls the method on the same flashlight. It returns a boolean, so it can be the condition of an `if`.","`if (this.isLow()) { return this.charge + \"% (low)\"; }`, and after it `return this.charge + \"%\";`"],"tests":[{"name":"Test 1","stdin":"","call":"Flashlight light = new Flashlight(30);\nSystem.out.println(light);\nlight.use(15);\nSystem.out.println(light);\n","expect":"30%\n15% (low)","hidden":false},{"name":"Test 2","stdin":"","call":"Flashlight light = new Flashlight(20);\nSystem.out.println(light);\nlight.use(1);\nSystem.out.println(light);\n","expect":"20%\n19% (low)","hidden":true},{"name":"Test 3","stdin":"","call":"Flashlight full = new Flashlight(100);\nFlashlight empty = new Flashlight(0);\nSystem.out.println(full + \" and \" + empty);\n","expect":"100% and 0% (low)","hidden":true}],"require":[{"pattern":"\\bisLow\\s*\\(","min":2,"message":"Let `toString` call `isLow()` to decide whether to add ` (low)`."},{"pattern":"\\bpublic\\s+String\\s+toString\\s*\\(\\s*\\)","message":"Write the method as `public String toString()`, so `println` uses it."}],"forbid":[],"more":[{"task":"An `EggCarton` holds at most 12 eggs. Add two methods. `add()` puts one egg in, unless the carton is full: use `isFull()` to check. `addMany(int count)` adds `count` eggs by calling `add()` that many times, so it can't overfill the carton either. The check adds 1 egg and then 8, prints the number of eggs, adds 8 more and prints it again:\n\n```\n9\n12\n```\n","kind":"code","seed":"// ==== EggCarton.java ====\npublic class EggCarton {\n    private int eggs;\n\n    public EggCarton() {\n        this.eggs = 0;\n    }\n\n    public int getEggs() {\n        return this.eggs;\n    }\n\n    public boolean isFull() {\n        return this.eggs == 12;\n    }\n\n    // Write the add and addMany methods here.\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        EggCarton carton = new EggCarton();\n        carton.addMany(14);\n        System.out.println(carton.getEggs() + \" eggs\");\n    }\n}\n","solution":"// ==== EggCarton.java ====\npublic class EggCarton {\n    private int eggs;\n\n    public EggCarton() {\n        this.eggs = 0;\n    }\n\n    public int getEggs() {\n        return this.eggs;\n    }\n\n    public boolean isFull() {\n        return this.eggs == 12;\n    }\n\n    public void add() {\n        if (!this.isFull()) {\n            this.eggs++;\n        }\n    }\n\n    public void addMany(int count) {\n        for (int i = 0; i < count; i++) {\n            this.add();\n        }\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        EggCarton carton = new EggCarton();\n        carton.addMany(14);\n        System.out.println(carton.getEggs() + \" eggs\");\n    }\n}\n","hints":["`add()` has an `if`: only when the carton is not full, `this.eggs++`. \"Not full\" is `!this.isFull()`.","`addMany` is a loop that runs `count` times and calls `this.add();` each time."],"tests":[{"name":"Test 1","stdin":"","call":"EggCarton carton = new EggCarton();\ncarton.add();\ncarton.addMany(8);\nSystem.out.println(carton.getEggs());\ncarton.addMany(8);\nSystem.out.println(carton.getEggs());\n","expect":"9\n12","hidden":false},{"name":"Test 2","stdin":"","call":"EggCarton carton = new EggCarton();\nfor (int i = 0; i < 13; i++) {\n    carton.add();\n}\nSystem.out.println(carton.getEggs());\nSystem.out.println(carton.isFull());\n","expect":"12\ntrue","hidden":true},{"name":"Test 3","stdin":"","call":"EggCarton first = new EggCarton();\nEggCarton second = new EggCarton();\nfirst.addMany(0);\nsecond.addMany(5);\nSystem.out.println(first.getEggs());\nSystem.out.println(second.getEggs());\n","expect":"0\n5","hidden":true}],"require":[{"pattern":"\\bisFull\\s*\\(","min":2,"message":"Let `add()` use `isFull()` to check for room."},{"pattern":"\\badd\\s*\\(\\s*\\)\\s*;","message":"Let `addMany` call `add()` in a loop."}],"forbid":[]},{"task":"What does this program print? Follow each call into the class and back out.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Frog frog = new Frog();\n        frog.hopMany(2);\n        frog.hop();\n        System.out.println(frog.getHops());\n    }\n}\n// ==== Frog.java ====\npublic class Frog {\n    private int hops;\n\n    public Frog() {\n        this.hops = 0;\n    }\n\n    public void hop() {\n        this.hops++;\n        System.out.println(\"hop \" + this.hops);\n    }\n\n    public void hopMany(int times) {\n        for (int i = 0; i < times; i++) {\n            this.hop();\n        }\n        System.out.println(\"rest after \" + times);\n    }\n\n    public int getHops() {\n        return this.hops;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Frog frog = new Frog();\n        frog.hopMany(2);\n        frog.hop();\n        System.out.println(frog.getHops());\n    }\n}\n// ==== Frog.java ====\npublic class Frog {\n    private int hops;\n\n    public Frog() {\n        this.hops = 0;\n    }\n\n    public void hop() {\n        this.hops++;\n        System.out.println(\"hop \" + this.hops);\n    }\n\n    public void hopMany(int times) {\n        for (int i = 0; i < times; i++) {\n            this.hop();\n        }\n        System.out.println(\"rest after \" + times);\n    }\n\n    public int getHops() {\n        return this.hops;\n    }\n}\n","hints":["`hopMany(2)` calls `hop()` twice, and each `hop()` prints the new count. Only after the loop does `hopMany` print its own line.","`main` then calls `hop()` directly, which makes it 3 hops."],"tests":[{"name":"Output","stdin":"","expect":"hop 1\nhop 2\nrest after 2\nhop 3\n3","hidden":false}],"require":[],"forbid":[],"lines":["hop 1","hop 2","rest after 2","hop 3","3"]}]}