{"id":"class-design-overloading","slug":"overloaded-methods","title":"Methods with the same name","text":"You've called one method name with all kinds of values since module 1: `System.out.println(\"Hi\")`, `System.out.println(42)`, `System.out.println(3.5)` and `System.out.println()`. That isn't one method that takes anything: `println` is several methods with the same name, one for each type of parameter. Like constructors, methods can be **overloaded**, and the methods of your own classes can be too:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        LabelPrinter printer = new LabelPrinter();\n        printer.print(\"Flour\");\n        printer.print(42);\n        printer.print(\"Sugar\", 2);\n        System.out.println(\"Labels printed: \" + printer.getPrinted());\n    }\n}\n// ==== LabelPrinter.java ====\npublic class LabelPrinter {\n    private int printed;\n\n    public LabelPrinter() {\n        this.printed = 0;\n    }\n\n    public void print(String text) {\n        System.out.println(\"[ \" + text + \" ]\");\n        this.printed = this.printed + 1;\n    }\n\n    public void print(int number) {\n        this.print(\"No. \" + number);\n    }\n\n    public void print(String text, int copies) {\n        for (int i = 0; i < copies; i++) {\n            this.print(text);\n        }\n    }\n\n    public int getPrinted() {\n        return this.printed;\n    }\n}\n```\n\n```output\n[ Flour ]\n[ No. 42 ]\n[ Sugar ]\n[ Sugar ]\nLabels printed: 4\n```\n\n- Three methods are called `print`. Java picks one by the values in the call: a String runs `print(String text)`, an int runs `print(int number)`, and a String and an int run `print(String text, int copies)`.\n- The other two call `print(String text)` instead of printing on their own, so how a label looks, and the counting, are written once. It's the same idea as `this(...)` in the last step, as an ordinary method call.\n- Overloading suits methods that do the same thing with different kinds of values. Methods that do different things should get different names.\n\n### Which one Java picks\n\nJava compares the values in the call with each method's parameters: how many there are, and their types, in order. What decides is the type of each value, not what it looks like when printed. Static methods can be overloaded too, so here's the idea in `Main` alone:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        show(5);\n        show(5.0);\n        show(\"5\");\n        show(2 + 3);\n        show(5 / 2.0);\n    }\n\n    public static void show(int value) {\n        System.out.println(\"int: \" + value);\n    }\n\n    public static void show(double value) {\n        System.out.println(\"double: \" + value);\n    }\n\n    public static void show(String value) {\n        System.out.println(\"String: \" + value);\n    }\n}\n```\n\n```output\nint: 5\ndouble: 5.0\nString: 5\nint: 5\ndouble: 2.5\n```\n\n- `5.0` is a double and `\"5\"` is a String, so each goes to its own method.\n- `2 + 3` is an int, and `5 / 2.0` a double, so the type of the result decides.\n- An int also fits a `double` parameter, just as `double distance = 5;` works (module 3). Without `show(int value)`, `show(5)` would run `show(double value)` and print `double: 5.0`. With both there, Java takes the one that fits exactly.\n\n### The return type doesn't count\n\nMethods, like constructors, differ only by their parameter types. Parameter names don't count, and neither does the return type. Say you want a method that returns a label's text instead of printing it, and you call it `print` too:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        LabelPrinter printer = new LabelPrinter();\n        printer.print(\"Salt\");\n    }\n}\n// ==== LabelPrinter.java ====\npublic class LabelPrinter {\n    public void print(String text) {\n        System.out.println(\"[ \" + text + \" ]\");\n    }\n\n    public String print(String label) {\n        return \"[ \" + label + \" ]\";\n    }\n}\n```\n\n```javac\nLabelPrinter.java:6: error: method print(String) is already defined in class LabelPrinter\n    public String print(String label) {\n                  ^\n1 error\n```\n\nA call such as `printer.print(\"Salt\");` doesn't have to use the value a method returns, so nothing in it could tell the two apart. A method that does something different gets a name of its own, such as `labelFor(String text)`.\n","task":"An `Odometer` counts the kilometers a car has driven, and `add(int km)` adds a trip. Add a second method, `add(int hours, int speed)`, for a trip of `hours` hours at `speed` kilometers an hour. It adds `hours * speed` kilometers by calling `add(int km)`. The check runs:\n\n```java\nOdometer odometer = new Odometer();\nodometer.add(35);\nodometer.add(2, 80);\nSystem.out.println(odometer);\n```\n\nand expects:\n\n```\n195 km\n```\n","kind":"code","seed":"// ==== Odometer.java ====\npublic class Odometer {\n    private int km;\n\n    public Odometer() {\n        this.km = 0;\n    }\n\n    public void add(int km) {\n        this.km = this.km + km;\n    }\n\n    // Write the second add method here.\n\n    public String toString() {\n        return this.km + \" km\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Odometer odometer = new Odometer();\n        odometer.add(35);\n        odometer.add(2, 80);\n        System.out.println(odometer);\n    }\n}\n","solution":"// ==== Odometer.java ====\npublic class Odometer {\n    private int km;\n\n    public Odometer() {\n        this.km = 0;\n    }\n\n    public void add(int km) {\n        this.km = this.km + km;\n    }\n\n    public void add(int hours, int speed) {\n        this.add(hours * speed);\n    }\n\n    public String toString() {\n        return this.km + \" km\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Odometer odometer = new Odometer();\n        odometer.add(35);\n        odometer.add(2, 80);\n        System.out.println(odometer);\n    }\n}\n","hints":["The new method has the same name and two int parameters: `public void add(int hours, int speed) {`.","It works out the kilometers and passes them on to the other `add`: `this.add(hours * speed);`."],"tests":[{"name":"Test 1","stdin":"","call":"Odometer odometer = new Odometer();\nodometer.add(35);\nodometer.add(2, 80);\nSystem.out.println(odometer);\n","expect":"195 km","hidden":false},{"name":"Test 2","stdin":"","call":"Odometer odometer = new Odometer();\nodometer.add(3, 50);\nSystem.out.println(odometer);\nodometer.add(1, 7);\nodometer.add(12);\nSystem.out.println(odometer);\n","expect":"150 km\n169 km","hidden":true},{"name":"Test 3","stdin":"","call":"Odometer odometer = new Odometer();\nodometer.add(0, 90);\nSystem.out.println(odometer);\n","expect":"0 km","hidden":true}],"require":[{"pattern":"\\badd\\s*\\(\\s*int\\s+\\w+\\s*,\\s*int\\s+\\w+\\s*\\)","message":"Write the second method as `public void add(int hours, int speed)`."},{"pattern":"\\badd\\s*\\(\\s*(?!int\\b)[a-z]","message":"Let the new method call `add` with the kilometers: `this.add(hours * speed);`."}],"forbid":[],"more":[{"task":"What does this program print? The kitchen scale has three `add` methods, and two of them call another one.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        KitchenScale scale = new KitchenScale();\n        scale.add(250);\n        scale.add(\"egg\");\n        scale.add(\"250\");\n        scale.add(40, 2);\n        System.out.println(scale.getGrams() + \" g in total\");\n    }\n}\n// ==== KitchenScale.java ====\npublic class KitchenScale {\n    private int grams;\n\n    public KitchenScale() {\n        this.grams = 0;\n    }\n\n    public void add(int grams) {\n        this.grams = this.grams + grams;\n        System.out.println(\"Added \" + grams + \" g\");\n    }\n\n    public void add(String item) {\n        if (item.equals(\"egg\")) {\n            this.add(60);\n        } else if (item.equals(\"apple\")) {\n            this.add(150);\n        } else {\n            System.out.println(\"Unknown: \" + item);\n        }\n    }\n\n    public void add(int grams, int times) {\n        for (int i = 0; i < times; i++) {\n            this.add(grams);\n        }\n    }\n\n    public int getGrams() {\n        return this.grams;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        KitchenScale scale = new KitchenScale();\n        scale.add(250);\n        scale.add(\"egg\");\n        scale.add(\"250\");\n        scale.add(40, 2);\n        System.out.println(scale.getGrams() + \" g in total\");\n    }\n}\n// ==== KitchenScale.java ====\npublic class KitchenScale {\n    private int grams;\n\n    public KitchenScale() {\n        this.grams = 0;\n    }\n\n    public void add(int grams) {\n        this.grams = this.grams + grams;\n        System.out.println(\"Added \" + grams + \" g\");\n    }\n\n    public void add(String item) {\n        if (item.equals(\"egg\")) {\n            this.add(60);\n        } else if (item.equals(\"apple\")) {\n            this.add(150);\n        } else {\n            System.out.println(\"Unknown: \" + item);\n        }\n    }\n\n    public void add(int grams, int times) {\n        for (int i = 0; i < times; i++) {\n            this.add(grams);\n        }\n    }\n\n    public int getGrams() {\n        return this.grams;\n    }\n}\n","hints":["`\"egg\"` is a String, so it runs `add(String item)`, which calls `add(int grams)` with 60. That's the method that prints `Added`.","`\"250\"` is in quotes, so it's a String too, and it isn't an egg or an apple. `add(40, 2)` calls `add(int grams)` twice, and each call prints a line. The total counts only what went through `add(int grams)`."],"tests":[{"name":"Output","stdin":"","expect":"Added 250 g\nAdded 60 g\nUnknown: 250\nAdded 40 g\nAdded 40 g\n390 g in total","hidden":false}],"require":[],"forbid":[],"lines":["Added 250 g","Added 60 g","Unknown: 250","Added 40 g","Added 40 g","390 g in total"]},{"task":"An `Alarm` is set with `set(int hours, int minutes)`. Add a second `set` method, `set(String time)`, that takes the time as text, like `\"6:45\"`: split it at the `:`, turn both parts into numbers, and call `set(int hours, int minutes)` with them. The check runs:\n\n```java\nAlarm alarm = new Alarm();\nalarm.set(7, 30);\nSystem.out.println(alarm);\nalarm.set(\"6:05\");\nSystem.out.println(alarm);\n```\n\nand expects:\n\n```\nAlarm at 7:30\nAlarm at 6:05\n```\n","kind":"code","seed":"// ==== Alarm.java ====\npublic class Alarm {\n    private int hours;\n    private int minutes;\n\n    public Alarm() {\n        this.hours = 7;\n        this.minutes = 0;\n    }\n\n    public void set(int hours, int minutes) {\n        this.hours = hours;\n        this.minutes = minutes;\n    }\n\n    // Write the set(String time) method here.\n\n    public String toString() {\n        if (this.minutes < 10) {\n            return \"Alarm at \" + this.hours + \":0\" + this.minutes;\n        }\n        return \"Alarm at \" + this.hours + \":\" + this.minutes;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Alarm alarm = new Alarm();\n        alarm.set(7, 30);\n        System.out.println(alarm);\n        alarm.set(\"6:05\");\n        System.out.println(alarm);\n    }\n}\n","solution":"// ==== Alarm.java ====\npublic class Alarm {\n    private int hours;\n    private int minutes;\n\n    public Alarm() {\n        this.hours = 7;\n        this.minutes = 0;\n    }\n\n    public void set(int hours, int minutes) {\n        this.hours = hours;\n        this.minutes = minutes;\n    }\n\n    public void set(String time) {\n        String[] parts = time.split(\":\");\n        this.set(Integer.valueOf(parts[0]), Integer.valueOf(parts[1]));\n    }\n\n    public String toString() {\n        if (this.minutes < 10) {\n            return \"Alarm at \" + this.hours + \":0\" + this.minutes;\n        }\n        return \"Alarm at \" + this.hours + \":\" + this.minutes;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Alarm alarm = new Alarm();\n        alarm.set(7, 30);\n        System.out.println(alarm);\n        alarm.set(\"6:05\");\n        System.out.println(alarm);\n    }\n}\n","hints":["The header is `public void set(String time) {`. Inside it, `String[] parts = time.split(\":\");` gives the hours in `parts[0]` and the minutes in `parts[1]`, as text.","`Integer.valueOf` turns each part into a number (`\"05\"` becomes 5). Then `this.set(Integer.valueOf(parts[0]), Integer.valueOf(parts[1]));` runs the other `set`."],"tests":[{"name":"Test 1","stdin":"","call":"Alarm alarm = new Alarm();\nalarm.set(7, 30);\nSystem.out.println(alarm);\nalarm.set(\"6:05\");\nSystem.out.println(alarm);\n","expect":"Alarm at 7:30\nAlarm at 6:05","hidden":false},{"name":"Test 2","stdin":"","call":"Alarm alarm = new Alarm();\nalarm.set(\"23:59\");\nSystem.out.println(alarm);\nalarm.set(\"0:07\");\nSystem.out.println(alarm);\n","expect":"Alarm at 23:59\nAlarm at 0:07","hidden":true},{"name":"Test 3","stdin":"","call":"Alarm alarm = new Alarm();\nSystem.out.println(alarm);\nalarm.set(\"12:00\");\nSystem.out.println(alarm);\n","expect":"Alarm at 7:00\nAlarm at 12:00","hidden":true}],"require":[{"pattern":"\\bset\\s*\\(\\s*String\\s+\\w+\\s*\\)","message":"Write the new method as `public void set(String time)`."},{"pattern":"\\.split\\s*\\(","message":"Split the time at the `:` with `split(\":\")`."},{"pattern":"\\bset\\s*\\(\\s*Integer\\.(valueOf|parseInt)\\s*\\(|\\bset\\s*\\(\\s*[a-z]\\w*\\s*,\\s*[a-z]\\w*\\s*\\)","message":"Let `set(String time)` call `set(int hours, int minutes)` with the two numbers, instead of storing them itself."}],"forbid":[]}]}