Java Arena
Step 2 of 8

An object inside an object

An instance variable can hold an object too. You've done it all along: an instance variable of type String holds a String object. In the same way, its type can be one of your own classes. A parcel has a recipient and a weight, and it goes to an address, which is a thing of its own, with a street, a house number and a city:

Main.java
public class Main {
    public static void main(String[] args) {
        Address address = new Address("Elm Street", 12, "Riverton");
        Parcel parcel = new Parcel("Amir", address, 1200);
        System.out.println(parcel);
        System.out.println(parcel.isGoingTo("Riverton"));
        System.out.println(parcel.isGoingTo("Lakeside"));
    }
}
Parcel.java
public class Parcel {
    private String recipient;
    private Address address;
    private int grams;

    public Parcel(String recipient, Address address, int grams) {
        this.recipient = recipient;
        this.address = address;
        this.grams = grams;
    }

    public boolean isGoingTo(String city) {
        return this.address.getCity().equals(city);
    }

    public String toString() {
        return this.recipient + ", " + this.address + " (" + this.grams + " g)";
    }
}
Address.java
public class Address {
    private String street;
    private int number;
    private String city;

    public Address(String street, int number, String city) {
        this.street = street;
        this.number = number;
        this.city = city;
    }

    public String getCity() {
        return this.city;
    }

    public String toString() {
        return this.street + " " + this.number + ", " + this.city;
    }
}
Output
Amir, Elm Street 12, Riverton (1200 g)
true
false
  • private Address address; is an instance variable like the others, and its type is the class Address. The constructor stores the Address it's given, just as it stores the name and the weight.
  • In toString, joining this.address to a String with + calls the address's own toString. The parcel doesn't need to know how an address is written out: that's the address's job.
  • isGoingTo asks the address for its city with this.address.getCity(), and then compares the city it gets back with equals. Calls can follow each other like this: each one is made on what the one before it returned.
  • A getter can return the inner object. With public Address getAddress() in Parcel, parcel.getAddress().getCity() asks the parcel for its address, and then the address for its city.

Keeping the address in a class of its own keeps both classes small, and a class for letters or for a delivery route could use the same Address class. If the constructor forgot to set this.address, it would stay null, and isGoingTo would crash with a NullPointerException (module 22).

Making the inner object in the constructor

The caller doesn't have to build the inner object. A constructor can make it from the values it's given:

public Parcel(String recipient, String street, int number, String city, int grams) {
    this.recipient = recipient;
    this.address = new Address(street, number, city);
    this.grams = grams;
}

With this constructor, new Parcel("Amir", "Elm Street", 12, "Riverton", 1200) makes the parcel and its address in one go. Either way, the parcel ends up with an Address object in its instance variable.

Your task

Challenge 1 of 3

A sports team has a name and a coach, and Coach.java is ready. In Team.java, add a private instance variable coach of type Coach, and change the constructor to Team(String name, Coach coach). Then write the method isCoachedBy(String coachName): it returns true when the team's coach has that name. Ask the coach for its name with getName(). The check runs:

Coach rosa = new Coach("Rosa", 12);
Team team = new Team("Hawks", rosa);
System.out.println(team.isCoachedBy("Rosa"));
System.out.println(team.isCoachedBy("Ken"));

and expects:

true
false

Challenge 2

What does this program print? Follow the Engine object: which variables refer to it?

Challenge 3

A train ticket keeps its route in a Route object, and Route.java is ready. In Ticket.java, write:

  • the constructor Ticket(String passenger, String from, String to), which stores the passenger and makes the route itself, from from and to;
  • the method goesTo(String city), which returns true when the ticket's route ends in that city. Ask the route where it ends with getTo().

The check runs:

Ticket ticket = new Ticket("Lea", "Harbor Town", "Hill Park");
System.out.println(ticket);
System.out.println(ticket.goesTo("Hill Park"));
System.out.println(ticket.goesTo("Harbor Town"));

and expects:

Lea: Harbor Town to Hill Park
true
false