As discussed in
Java Class, we can have classes as part of another class.
i.e. we can have a user defined type inside another user defined type.
e.g., room having fan and lights, car having engine and tyres. This way of including classes inside other classes is also referred as
class composition or
has a relation. That is similar to car is composed of engine, tyres and seats or room has a fan etc.,.
There is no limit on the level of composition. An apartment contains multiple flats, a flat contains multiple rooms, rooms contain fans and lights and fans contain motor, wings etc.,.
Similar to primitive data types, the dot(
.
) operator can also be used to access the variables of user defined types (non primitive types). Since there is no limit on the level to which classes can composed, there is also no limit on the number of levels to which the dot operators can be used.
The below program shows how classes can be composed of other classes and how those objects can be accessed.
Class Composition
class ClassComposition
{
public static void main(String arg[])
{
Room hall = new Room("Hall"); // LINE A
hall.area = 200.0;
hall.paintColor = "Voilet";
hall.flooring = "Marble";
hall.ceilingFan = new Fan("Bajaj"); // LINE B
hall.ceilingFan.speed = 500; // LINE B1
hall.ceilingFan.numberOfSpeeds = 5;
hall.tube = new Light("Hall tube light"); // LINE C
hall.tube.color = "White";
hall.tube.watts = 40;
hall.tube.tube = true; // LINE C1
Light bl = new Light("Yellow bed light"); // LINE D
hall.bedLight = bl;
hall.bedLight.color = "Yellow";
hall.bedLight.watts = 50;
hall.bedLight.tube = false;
System.out.println("Hall fan speed : " + hall.ceilingFan.speed);
System.out.println("Bed Light color : " + hall.bedLight.color);
}
}
class Fan
{
String name;
double speed;
String color;
int numberOfSpeeds;
Fan(String name)
{
this.name = name;
}
}
class Light
{
String name;
String color;
int watts;
boolean tube;
Light(String name)
{
this.name = name;
}
}
class Room
{
String name;
double area;
String paintColor;
String flooring;
Fan ceilingFan;
Light tube;
Light bedLight;
Room(String name)
{
this.name = name;
}
}
OUTPUTHall fan speed : 500.0
Bed Light color : Yellow
DESCRIPTIONHere we have defined 3 classes - Fan
, Light
and Room
. At LINE A
, we have created an object of Room
class, at LINE B
we have created an object of Fan
class, at LINE C
and LINE D
we have created two objects of Light
class - one is a tube light and the other is bed light.
The variables of the composed class Fan
can be accessed using dot operator. At LINE B1
we have accessed hall.ceilingFan.speed
and assigned it a speed of 500
. Here hall
is object of Room
class, ceilingFan
is object of Fan
class and speed
variable in the ceilingFan
object is changed.
If we observe carefully in LINE C
, we have tube
variable in Room
class and also tube
variable in Light
class. So hall.tube
refers to the Light
object in Room
class, where as hall.tube.tube
refers to a boolean
datatype. This hall.tube.tube
tells if the Light
object is a tube or not. Although both of them have the same variable name, the scope is different. hall.tube
is in the scope of Room
object and hall.tube.tube
is in the scope of Light
object inside the Room
object.
Also note that we have created two references to the Bed light object. The reference bl
and hall.bedLight
point to the same object. Either bl.watts
is assigned to 50
or hall.bedLight.color
is assigned "Yellow"
, both of them point to the same bed light object created at LINE D
. Refer to Java Objects References and Class References And Objects In Java for more details about the references and objects.
THINGS TO TRY
- Add a
tableFan
variable to the Room
class and initialize data to it.
- Try setting the value of
hall.ceilingFan.speed
to 200
before LINE B
. Since we have not created the Fan
object, the hall.ceilingFan
contains null
, as the object references are by default initialized to null
. We will get a NullPointerException
when we try to access a reference which is null
.
- Create one more constructor for
Light
class which takes name
, watts
, color
and whether tube
or not. Initialize the member variables in the constructor using this
keyword. Also change the code in the main method to use the newly created constructor. Observe how much duplicate code is reduced.