{"id":"object-interaction-same-class","slug":"same-class-parameter","title":"Comparing with another object of the same class","text":"A parameter can also be an object of the method's own class. That's how an object compares itself with another of its kind. Is this parcel heavier than that one?\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Parcel small = new Parcel(\"Lina\", 400);\n        Parcel big = new Parcel(\"Omar\", 2500);\n        System.out.println(big.isHeavierThan(small));\n        System.out.println(small.isHeavierThan(big));\n        System.out.println(small.isHeavierThan(small));\n        System.out.println(big.gramsMoreThan(small));\n    }\n}\n// ==== Parcel.java ====\npublic class Parcel {\n    private String recipient;\n    private int grams;\n\n    public Parcel(String recipient, int grams) {\n        this.recipient = recipient;\n        this.grams = grams;\n    }\n\n    public boolean isHeavierThan(Parcel other) {\n        return this.grams > other.grams;\n    }\n\n    public int gramsMoreThan(Parcel other) {\n        return this.grams - other.grams;\n    }\n\n    public String toString() {\n        return \"Parcel for \" + this.recipient + \", \" + this.grams + \" g\";\n    }\n}\n```\n\n```output\ntrue\nfalse\nfalse\n2100\n```\n\n- In `big.isHeavierThan(small)`, `this` is `big`, the object before the dot, and `other` is `small`, the one in the parentheses. The method compares the two.\n- `other.grams` reads the other parcel's private variable, and that's allowed. `private` means *only the code of the class Parcel*, not *only this object*: code written in Parcel may use the private variables of any Parcel. In `Main`, `small.grams` still doesn't compile.\n- `small.isHeavierThan(small)` compares the parcel with itself, and a parcel isn't heavier than itself: `>` is false for equal weights. The same goes for two different parcels of the same weight: neither is heavier than the other.\n- `gramsMoreThan` answers with a number instead of true or false: how many grams more this parcel weighs than the other one.\n\nThe parameter's name, `other`, is only a name: `compared` or `another` work just as well. If the class has getters, `other.getGrams()` works too, but inside the class, reading the variable directly is just as good.\n\n### Letting the class compare\n\nWith `isHeavierThan`, finding the heaviest parcel in a list is the loop from module 19, but the comparison is the parcel's own method:\n\n```java\nParcel heaviest = parcels.get(0);\nfor (Parcel parcel : parcels) {\n    if (parcel.isHeavierThan(heaviest)) {\n        heaviest = parcel;\n    }\n}\n```\n\nThe loop doesn't need to know how parcels are compared, or even that they're weighed in grams. How to compare two parcels is written once, in the class, and every part of the program asks the class.\n","task":"In `Mountain.java`, write the method `isHigherThan(Mountain other)`. It returns `true` when this mountain is higher than the other one, and `false` otherwise (also when both are equally high). The check runs:\n\n```java\nMountain grayPeak = new Mountain(\"Gray Peak\", 2410);\nMountain redHill = new Mountain(\"Red Hill\", 980);\nSystem.out.println(grayPeak.isHigherThan(redHill));\nSystem.out.println(redHill.isHigherThan(grayPeak));\n```\n\nand expects:\n\n```\ntrue\nfalse\n```\n","kind":"code","seed":"// ==== Mountain.java ====\npublic class Mountain {\n    private String name;\n    private int meters;\n\n    public Mountain(String name, int meters) {\n        this.name = name;\n        this.meters = meters;\n    }\n\n    // Write the isHigherThan method here.\n\n    public String toString() {\n        return this.name + \" (\" + this.meters + \" m)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Mountain grayPeak = new Mountain(\"Gray Peak\", 2410);\n        Mountain redHill = new Mountain(\"Red Hill\", 980);\n        System.out.println(grayPeak.isHigherThan(redHill));\n        System.out.println(redHill.isHigherThan(grayPeak));\n    }\n}\n","solution":"// ==== Mountain.java ====\npublic class Mountain {\n    private String name;\n    private int meters;\n\n    public Mountain(String name, int meters) {\n        this.name = name;\n        this.meters = meters;\n    }\n\n    public boolean isHigherThan(Mountain other) {\n        return this.meters > other.meters;\n    }\n\n    public String toString() {\n        return this.name + \" (\" + this.meters + \" m)\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Mountain grayPeak = new Mountain(\"Gray Peak\", 2410);\n        Mountain redHill = new Mountain(\"Red Hill\", 980);\n        System.out.println(grayPeak.isHigherThan(redHill));\n        System.out.println(redHill.isHigherThan(grayPeak));\n    }\n}\n","hints":["The parameter is a Mountain: `public boolean isHigherThan(Mountain other) {`.","Compare this mountain's meters with the other's. The method is in the Mountain class, so it may read `other.meters`: `return this.meters > other.meters;`."],"tests":[{"name":"Test 1","stdin":"","call":"Mountain grayPeak = new Mountain(\"Gray Peak\", 2410);\nMountain redHill = new Mountain(\"Red Hill\", 980);\nSystem.out.println(grayPeak.isHigherThan(redHill));\nSystem.out.println(redHill.isHigherThan(grayPeak));\n","expect":"true\nfalse","hidden":false},{"name":"Test 2","stdin":"","call":"Mountain north = new Mountain(\"North Top\", 1500);\nMountain south = new Mountain(\"South Top\", 1500);\nSystem.out.println(north.isHigherThan(south));\nSystem.out.println(south.isHigherThan(north));\nSystem.out.println(north.isHigherThan(north));\n","expect":"false\nfalse\nfalse","hidden":true},{"name":"Test 3","stdin":"","call":"Mountain low = new Mountain(\"Mole Hill\", 12);\nMountain high = new Mountain(\"Cloud Peak\", 4001);\nMountain middle = new Mountain(\"Wind Ridge\", 1999);\nSystem.out.println(middle.isHigherThan(low) + \" \" + middle.isHigherThan(high));\nSystem.out.println(high.isHigherThan(middle) + \" \" + low.isHigherThan(middle));\n","expect":"true false\ntrue false","hidden":true}],"require":[{"pattern":"\\bpublic\\s+boolean\\s+isHigherThan\\s*\\(\\s*Mountain\\s+\\w+\\s*\\)","message":"Write the method as `public boolean isHigherThan(Mountain other)`."}],"forbid":[],"more":[{"task":"Packing to move house: a box fits inside another box when it's smaller in all three measures, so that its width, its height and its depth are each less than the other box's. (The boxes aren't turned around.) In `Box.java`, write the method `fitsInside(Box other)`. The check runs:\n\n```java\nBox shoebox = new Box(30, 12, 18);\nBox crate = new Box(50, 40, 40);\nSystem.out.println(shoebox.fitsInside(crate));\nSystem.out.println(crate.fitsInside(shoebox));\n```\n\nand expects:\n\n```\ntrue\nfalse\n```\n","kind":"code","seed":"// ==== Box.java ====\npublic class Box {\n    private int width;\n    private int height;\n    private int depth;\n\n    public Box(int width, int height, int depth) {\n        this.width = width;\n        this.height = height;\n        this.depth = depth;\n    }\n\n    // Write the fitsInside method here.\n\n    public String toString() {\n        return this.width + \" x \" + this.height + \" x \" + this.depth + \" cm\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Box shoebox = new Box(30, 12, 18);\n        Box crate = new Box(50, 40, 40);\n        System.out.println(shoebox.fitsInside(crate));\n        System.out.println(crate.fitsInside(shoebox));\n    }\n}\n","solution":"// ==== Box.java ====\npublic class Box {\n    private int width;\n    private int height;\n    private int depth;\n\n    public Box(int width, int height, int depth) {\n        this.width = width;\n        this.height = height;\n        this.depth = depth;\n    }\n\n    public boolean fitsInside(Box other) {\n        return this.width < other.width && this.height < other.height && this.depth < other.depth;\n    }\n\n    public String toString() {\n        return this.width + \" x \" + this.height + \" x \" + this.depth + \" cm\";\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Box shoebox = new Box(30, 12, 18);\n        Box crate = new Box(50, 40, 40);\n        System.out.println(shoebox.fitsInside(crate));\n        System.out.println(crate.fitsInside(shoebox));\n    }\n}\n","hints":["Three comparisons, one for each measure, and all three must be true: join them with `&&`.","`return this.width < other.width && this.height < other.height && this.depth < other.depth;`"],"tests":[{"name":"Test 1","stdin":"","call":"Box shoebox = new Box(30, 12, 18);\nBox crate = new Box(50, 40, 40);\nSystem.out.println(shoebox.fitsInside(crate));\nSystem.out.println(crate.fitsInside(shoebox));\n","expect":"true\nfalse","hidden":false},{"name":"Test 2","stdin":"","call":"Box crate = new Box(50, 40, 40);\nSystem.out.println(new Box(60, 10, 10).fitsInside(crate));\nSystem.out.println(new Box(10, 45, 10).fitsInside(crate));\nSystem.out.println(new Box(10, 10, 41).fitsInside(crate));\nSystem.out.println(new Box(49, 39, 39).fitsInside(crate));\n","expect":"false\nfalse\nfalse\ntrue","hidden":true},{"name":"Test 3","stdin":"","call":"Box cube = new Box(20, 20, 20);\nBox same = new Box(20, 20, 20);\nSystem.out.println(cube.fitsInside(same));\nSystem.out.println(cube.fitsInside(cube));\nSystem.out.println(new Box(19, 20, 19).fitsInside(cube));\n","expect":"false\nfalse\nfalse","hidden":true}],"require":[{"pattern":"\\bpublic\\s+boolean\\s+fitsInside\\s*\\(\\s*Box\\s+\\w+\\s*\\)","message":"Write the method as `public boolean fitsInside(Box other)`."}],"forbid":[]},{"task":"What does this program print? A racer beats another one with a smaller time, and the loop keeps the best racer so far.\n","kind":"predict","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Racer> racers = new ArrayList<>();\n        racers.add(new Racer(\"Joe\", 61));\n        racers.add(new Racer(\"Ida\", 58));\n        racers.add(new Racer(\"Kai\", 58));\n        racers.add(new Racer(\"Liv\", 60));\n\n        Racer winner = racers.get(0);\n        for (Racer racer : racers) {\n            if (racer.beats(winner)) {\n                winner = racer;\n            }\n        }\n        System.out.println(winner);\n        System.out.println(winner.beats(racers.get(2)));\n    }\n}\n// ==== Racer.java ====\npublic class Racer {\n    private String name;\n    private int seconds;\n\n    public Racer(String name, int seconds) {\n        this.name = name;\n        this.seconds = seconds;\n    }\n\n    public boolean beats(Racer other) {\n        return this.seconds < other.seconds;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.seconds + \" s\";\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Racer> racers = new ArrayList<>();\n        racers.add(new Racer(\"Joe\", 61));\n        racers.add(new Racer(\"Ida\", 58));\n        racers.add(new Racer(\"Kai\", 58));\n        racers.add(new Racer(\"Liv\", 60));\n\n        Racer winner = racers.get(0);\n        for (Racer racer : racers) {\n            if (racer.beats(winner)) {\n                winner = racer;\n            }\n        }\n        System.out.println(winner);\n        System.out.println(winner.beats(racers.get(2)));\n    }\n}\n// ==== Racer.java ====\npublic class Racer {\n    private String name;\n    private int seconds;\n\n    public Racer(String name, int seconds) {\n        this.name = name;\n        this.seconds = seconds;\n    }\n\n    public boolean beats(Racer other) {\n        return this.seconds < other.seconds;\n    }\n\n    public String toString() {\n        return this.name + \", \" + this.seconds + \" s\";\n    }\n}\n","hints":["The winner starts as Joe (61 s). Ida's 58 beats it, so Ida becomes the winner. Kai's 58 doesn't beat Ida's 58: `<` is false for equal times. Liv's 60 doesn't either.","The last line asks whether the winner, Ida, beats `racers.get(2)`, which is Kai. Both have 58 seconds."],"tests":[{"name":"Output","stdin":"","expect":"Ida, 58 s\nfalse","hidden":false}],"require":[],"forbid":[],"lines":["Ida, 58 s","false"]}]}