{"id":"object-interaction-together","slug":"objects-working-together","title":"Several objects working together","text":"Programs are usually made of several classes, each with a job of its own, and their objects use each other. Here's a small football tournament:\n\n- A `Team` keeps its own name and points.\n- A `Match` knows its two teams and the goals they scored, and the rule for giving points: 3 to the winner, and 1 to each team for a draw.\n- `main` only sets things up and prints.\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Team owls = new Team(\"Owls\");\n        Team foxes = new Team(\"Foxes\");\n        Team bears = new Team(\"Bears\");\n\n        Match first = new Match(owls, foxes, 2, 1);\n        Match second = new Match(foxes, bears, 0, 0);\n        Match third = new Match(bears, owls, 3, 1);\n        first.givePoints();\n        second.givePoints();\n        third.givePoints();\n\n        System.out.println(first);\n        System.out.println(second);\n        System.out.println(third);\n        System.out.println(owls);\n        System.out.println(foxes);\n        System.out.println(bears);\n    }\n}\n// ==== Match.java ====\npublic class Match {\n    private Team home;\n    private Team away;\n    private int homeGoals;\n    private int awayGoals;\n\n    public Match(Team home, Team away, int homeGoals, int awayGoals) {\n        this.home = home;\n        this.away = away;\n        this.homeGoals = homeGoals;\n        this.awayGoals = awayGoals;\n    }\n\n    public void givePoints() {\n        if (this.homeGoals > this.awayGoals) {\n            this.home.addPoints(3);\n        } else if (this.awayGoals > this.homeGoals) {\n            this.away.addPoints(3);\n        } else {\n            this.home.addPoints(1);\n            this.away.addPoints(1);\n        }\n    }\n\n    public String toString() {\n        return this.home.getName() + \" \" + this.homeGoals + \"-\" + this.awayGoals + \" \" + this.away.getName();\n    }\n}\n// ==== Team.java ====\npublic class Team {\n    private String name;\n    private int points;\n\n    public Team(String name) {\n        this.name = name;\n        this.points = 0;\n    }\n\n    public void addPoints(int points) {\n        this.points = this.points + points;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String toString() {\n        return this.name + \", points: \" + this.points;\n    }\n}\n```\n\n```output\nOwls 2-1 Foxes\nFoxes 0-0 Bears\nBears 3-1 Owls\nOwls, points: 3\nFoxes, points: 1\nBears, points: 4\n```\n\n- A Match has two Team objects as instance variables (step 2). They aren't copies: `first` and `third` both refer to the one Owls object that `owls` refers to, so the points from both matches add up in the same team.\n- `givePoints` changes the teams through their own method, `addPoints` (step 1). It can't touch a team's `points` directly, and it doesn't need to.\n- The match's `toString` asks the teams for their names with `getName()`, because the result line should show only the names, not the points.\n\nEach class does one job. Team doesn't know the rules of football, and Match doesn't keep a table. A tournament that gave 2 points for a win would change only `givePoints`.\n\n### Planning a program of several classes\n\nWhen you plan a program like this, go through its data and its rules. For each piece of data, ask which object it belongs to: the points belong to a team, the goals to a match. For each rule, ask which class knows enough to apply it: giving points needs both teams and both scores, and only a Match has all four. The class that has the data is usually the one that gets the method.\n","task":"Add a method `winner()` to `Match`. It returns the team that scored more goals, or `null` when the match is a draw (`null` means *no object*, module 22). It returns one of the match's own Team objects, not a new team. `Team.java` and `Main.java` are ready, and `main` prints the winner's name, or `Draw`. For the matches in `main`, the program prints:\n\n```\nOwls\nBears\nDraw\n```\n","kind":"code","seed":"// ==== Match.java ====\npublic class Match {\n    private Team home;\n    private Team away;\n    private int homeGoals;\n    private int awayGoals;\n\n    public Match(Team home, Team away, int homeGoals, int awayGoals) {\n        this.home = home;\n        this.away = away;\n        this.homeGoals = homeGoals;\n        this.awayGoals = awayGoals;\n    }\n\n    // Write the winner method here.\n\n    public String toString() {\n        return this.home.getName() + \" \" + this.homeGoals + \"-\" + this.awayGoals + \" \" + this.away.getName();\n    }\n}\n\n// ==== Team.java ====\npublic class Team {\n    private String name;\n    private int points;\n\n    public Team(String name) {\n        this.name = name;\n        this.points = 0;\n    }\n\n    public void addPoints(int points) {\n        this.points = this.points + points;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String toString() {\n        return this.name + \", points: \" + this.points;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Team owls = new Team(\"Owls\");\n        Team foxes = new Team(\"Foxes\");\n        Team bears = new Team(\"Bears\");\n        printWinner(new Match(owls, foxes, 2, 1));\n        printWinner(new Match(owls, bears, 0, 2));\n        printWinner(new Match(foxes, bears, 1, 1));\n    }\n\n    public static void printWinner(Match match) {\n        Team winner = match.winner();\n        if (winner == null) {\n            System.out.println(\"Draw\");\n        } else {\n            System.out.println(winner.getName());\n        }\n    }\n}\n","solution":"// ==== Match.java ====\npublic class Match {\n    private Team home;\n    private Team away;\n    private int homeGoals;\n    private int awayGoals;\n\n    public Match(Team home, Team away, int homeGoals, int awayGoals) {\n        this.home = home;\n        this.away = away;\n        this.homeGoals = homeGoals;\n        this.awayGoals = awayGoals;\n    }\n\n    public Team winner() {\n        if (this.homeGoals > this.awayGoals) {\n            return this.home;\n        }\n        if (this.awayGoals > this.homeGoals) {\n            return this.away;\n        }\n        return null;\n    }\n\n    public String toString() {\n        return this.home.getName() + \" \" + this.homeGoals + \"-\" + this.awayGoals + \" \" + this.away.getName();\n    }\n}\n\n// ==== Team.java ====\npublic class Team {\n    private String name;\n    private int points;\n\n    public Team(String name) {\n        this.name = name;\n        this.points = 0;\n    }\n\n    public void addPoints(int points) {\n        this.points = this.points + points;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String toString() {\n        return this.name + \", points: \" + this.points;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Team owls = new Team(\"Owls\");\n        Team foxes = new Team(\"Foxes\");\n        Team bears = new Team(\"Bears\");\n        printWinner(new Match(owls, foxes, 2, 1));\n        printWinner(new Match(owls, bears, 0, 2));\n        printWinner(new Match(foxes, bears, 1, 1));\n    }\n\n    public static void printWinner(Match match) {\n        Team winner = match.winner();\n        if (winner == null) {\n            System.out.println(\"Draw\");\n        } else {\n            System.out.println(winner.getName());\n        }\n    }\n}\n","hints":["The method returns a Team: `public Team winner() {`. Compare `this.homeGoals` and `this.awayGoals`.","Return the team itself: `return this.home;` or `return this.away;`. When neither scored more, `return null;`."],"tests":[{"name":"The program","stdin":"","expect":"Owls\nBears\nDraw","hidden":false},{"name":"Test 2","stdin":"","call":"Team kites = new Team(\"Kites\");\nTeam moles = new Team(\"Moles\");\nMatch match = new Match(kites, moles, 0, 5);\nSystem.out.println(match.winner() == moles);\nSystem.out.println(match.winner() == kites);\nSystem.out.println(new Match(kites, moles, 3, 3).winner() == null);\n","expect":"true\nfalse\ntrue","hidden":true},{"name":"Test 3","stdin":"","call":"Team hares = new Team(\"Hares\");\nTeam crows = new Team(\"Crows\");\nhares.addPoints(9);\nMatch match = new Match(hares, crows, 4, 3);\nSystem.out.println(match.winner());\nSystem.out.println(new Match(crows, hares, 0, 0).winner());\n","expect":"Hares, points: 9\nnull","hidden":true}],"require":[{"pattern":"\\bpublic\\s+Team\\s+winner\\s*\\(\\s*\\)","message":"Write the method as `public Team winner()`."}],"forbid":[],"more":[{"task":"What does this program print? It uses `Team` and `Match` classes like the ones in the lesson. Watch when points are given, and which variables refer to the same team.\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Team owls = new Team(\"Owls\");\n        Team foxes = new Team(\"Foxes\");\n        Team favorite = foxes;\n        Match first = new Match(owls, foxes, 1, 1);\n        Match second = new Match(foxes, owls, 2, 0);\n        Match third = new Match(owls, favorite, 1, 3);\n        first.givePoints();\n        second.givePoints();\n        System.out.println(owls);\n        System.out.println(favorite);\n        third.givePoints();\n        System.out.println(foxes);\n    }\n}\n// ==== Match.java ====\npublic class Match {\n    private Team home;\n    private Team away;\n    private int homeGoals;\n    private int awayGoals;\n\n    public Match(Team home, Team away, int homeGoals, int awayGoals) {\n        this.home = home;\n        this.away = away;\n        this.homeGoals = homeGoals;\n        this.awayGoals = awayGoals;\n    }\n\n    public void givePoints() {\n        if (this.homeGoals > this.awayGoals) {\n            this.home.addPoints(3);\n        } else if (this.awayGoals > this.homeGoals) {\n            this.away.addPoints(3);\n        } else {\n            this.home.addPoints(1);\n            this.away.addPoints(1);\n        }\n    }\n}\n// ==== Team.java ====\npublic class Team {\n    private String name;\n    private int points;\n\n    public Team(String name) {\n        this.name = name;\n        this.points = 0;\n    }\n\n    public void addPoints(int points) {\n        this.points = this.points + points;\n    }\n\n    public String toString() {\n        return this.name + \", points: \" + this.points;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Team owls = new Team(\"Owls\");\n        Team foxes = new Team(\"Foxes\");\n        Team favorite = foxes;\n        Match first = new Match(owls, foxes, 1, 1);\n        Match second = new Match(foxes, owls, 2, 0);\n        Match third = new Match(owls, favorite, 1, 3);\n        first.givePoints();\n        second.givePoints();\n        System.out.println(owls);\n        System.out.println(favorite);\n        third.givePoints();\n        System.out.println(foxes);\n    }\n}\n// ==== Match.java ====\npublic class Match {\n    private Team home;\n    private Team away;\n    private int homeGoals;\n    private int awayGoals;\n\n    public Match(Team home, Team away, int homeGoals, int awayGoals) {\n        this.home = home;\n        this.away = away;\n        this.homeGoals = homeGoals;\n        this.awayGoals = awayGoals;\n    }\n\n    public void givePoints() {\n        if (this.homeGoals > this.awayGoals) {\n            this.home.addPoints(3);\n        } else if (this.awayGoals > this.homeGoals) {\n            this.away.addPoints(3);\n        } else {\n            this.home.addPoints(1);\n            this.away.addPoints(1);\n        }\n    }\n}\n// ==== Team.java ====\npublic class Team {\n    private String name;\n    private int points;\n\n    public Team(String name) {\n        this.name = name;\n        this.points = 0;\n    }\n\n    public void addPoints(int points) {\n        this.points = this.points + points;\n    }\n\n    public String toString() {\n        return this.name + \", points: \" + this.points;\n    }\n}\n","hints":["Making a Match gives no points: only `givePoints()` does. After the first two matches, the draw has given each team 1 point, and the Foxes won the second match for 3 more.","`favorite` refers to the same team as `foxes`. The third match is a Foxes win too, but its points come only when `third.givePoints()` runs, after the first two lines are printed."],"tests":[{"name":"Output","stdin":"","expect":"Owls, points: 1\nFoxes, points: 4\nFoxes, points: 7","hidden":false}],"require":[],"forbid":[],"lines":["Owls, points: 1","Foxes, points: 4","Foxes, points: 7"]},{"task":"An auction keeps the best bid so far in its instance variable `best`, which is `null` until the first bid comes in. `Bid.java` is ready, with the method `isHigherThan(Bid other)`. In `Auction.java`, write the method `offer(Bid bid)`: the bid becomes the best one when there's no best bid yet, or when it's higher than the best one. A bid that's only as high as the best one doesn't count, so the earlier bidder stays ahead. Compare the bids with `isHigherThan`.\n\n`Main.java` is ready: it reads bids such as `Mia 40` (a name and euros) until an empty line, and prints the auction before and after. For the input shown below, it prints:\n\n```\nPainting: no bids yet\nPainting: Sam (55 euros)\n```\n","kind":"code","seed":"// ==== Auction.java ====\npublic class Auction {\n    private String item;\n    private Bid best;\n\n    public Auction(String item) {\n        this.item = item;\n        this.best = null;\n    }\n\n    // Write the offer method here.\n\n    public String toString() {\n        if (this.best == null) {\n            return this.item + \": no bids yet\";\n        }\n        return this.item + \": \" + this.best;\n    }\n}\n\n// ==== Bid.java ====\npublic class Bid {\n    private String bidder;\n    private int euros;\n\n    public Bid(String bidder, int euros) {\n        this.bidder = bidder;\n        this.euros = euros;\n    }\n\n    public boolean isHigherThan(Bid other) {\n        return this.euros > other.euros;\n    }\n\n    public String toString() {\n        return this.bidder + \" (\" + this.euros + \" euros)\";\n    }\n}\n\n// ==== Main.java ====\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        Auction auction = new Auction(\"Painting\");\n        System.out.println(auction);\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.isEmpty()) {\n                break;\n            }\n            String[] parts = line.split(\" \");\n            auction.offer(new Bid(parts[0], Integer.valueOf(parts[1])));\n        }\n        System.out.println(auction);\n    }\n}\n","solution":"// ==== Auction.java ====\npublic class Auction {\n    private String item;\n    private Bid best;\n\n    public Auction(String item) {\n        this.item = item;\n        this.best = null;\n    }\n\n    public void offer(Bid bid) {\n        if (this.best == null || bid.isHigherThan(this.best)) {\n            this.best = bid;\n        }\n    }\n\n    public String toString() {\n        if (this.best == null) {\n            return this.item + \": no bids yet\";\n        }\n        return this.item + \": \" + this.best;\n    }\n}\n\n// ==== Bid.java ====\npublic class Bid {\n    private String bidder;\n    private int euros;\n\n    public Bid(String bidder, int euros) {\n        this.bidder = bidder;\n        this.euros = euros;\n    }\n\n    public boolean isHigherThan(Bid other) {\n        return this.euros > other.euros;\n    }\n\n    public String toString() {\n        return this.bidder + \" (\" + this.euros + \" euros)\";\n    }\n}\n\n// ==== Main.java ====\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        Auction auction = new Auction(\"Painting\");\n        System.out.println(auction);\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.isEmpty()) {\n                break;\n            }\n            String[] parts = line.split(\" \");\n            auction.offer(new Bid(parts[0], Integer.valueOf(parts[1])));\n        }\n        System.out.println(auction);\n    }\n}\n","hints":["The bid becomes the best one in two cases: when there's no best bid yet (`this.best` is `null`), or when the bid is higher than the best one. Check for `null` first, so that `isHigherThan` is never given `null`.","`if (this.best == null || bid.isHigherThan(this.best)) { this.best = bid; }`. With `||`, the second part runs only when the first is false, that is, when there is a best bid."],"tests":[{"name":"Test 1","stdin":"Mia 40\nSam 55\nAda 50\nLeo 55\n\n","expect":"Painting: no bids yet\nPainting: Sam (55 euros)","hidden":false},{"name":"Test 2","stdin":"\n","expect":"Painting: no bids yet\nPainting: no bids yet","hidden":true},{"name":"Test 3","stdin":"Zoe 5\n\n","expect":"Painting: no bids yet\nPainting: Zoe (5 euros)","hidden":true},{"name":"Test 4","stdin":"Ann 10\nBo 20\nCy 30\nDi 25\n\n","expect":"Painting: no bids yet\nPainting: Cy (30 euros)","hidden":true},{"name":"Test 5","stdin":"","call":"Auction auction = new Auction(\"Lamp\");\nauction.offer(new Bid(\"Kim\", 10));\nauction.offer(new Bid(\"Lou\", 10));\nauction.offer(new Bid(\"Max\", 9));\nSystem.out.println(auction);\n","expect":"Lamp: Kim (10 euros)","hidden":true}],"require":[{"pattern":"\\bpublic\\s+void\\s+offer\\s*\\(\\s*Bid\\s+\\w+\\s*\\)","message":"Write the method as `public void offer(Bid bid)`."},{"pattern":"\\.isHigherThan\\s*\\(","message":"Compare the bids with the bid's `isHigherThan` method."}],"forbid":[]}]}