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:
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"));
}
}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)";
}
}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;
}
}Amir, Elm Street 12, Riverton (1200 g)
true
falseprivate Address address;is an instance variable like the others, and its type is the classAddress. The constructor stores the Address it's given, just as it stores the name and the weight.- In
toString, joiningthis.addressto a String with+calls the address's owntoString. The parcel doesn't need to know how an address is written out: that's the address's job. isGoingToasks the address for its city withthis.address.getCity(), and then compares the city it gets back withequals. 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.