3. The is Operator

Now, in the real world, cars, trucks, and motorcycles are in fact vehicles. The same is true in a program. That is, an object of type Car or Truck or Motorcycle is automatically an object of type Vehicle. This brings us to the following Important Fact:

A reference variable whose data type is X can hold a reference to an object of class X, as well as any child class of X.

The practical effect of this in our example is that an object of type Car can be assigned to a variable of type Vehicle. That is, it would be legal to say

Vehicle myVehicle = myCar;

or even

Vehicle myVehicle = new Car();

After either of these statements, the variable myVehicle holds a reference to a Vehicle object that happens to be an instance of the subclass, Car. The object "remembers" that it is in fact a Car, and not just a Vehicle. Information about the actual class of an object is stored as part of that object. It is even possible to test whether a given object belongs to a given class using the is operator. The test:

if (myVehicle is Car) ...

determines whether the object referred to by myVehicle is in fact a car.

On the other hand, the assignment statement

myCar = myVehicle;

would be illegal because myVehicle could potentially refer to other types of vehicles that are not cars. This is similar to a problem we saw previously: The computer will not allow you to assign an int value to a variable of type short, because not every int is a short. Similarly, it will not allow you to assign a value of type Vehicle to a variable of type Car because not every vehicle is a car. As in the case of ints and shorts, the solution here is to use type-casting. If, for some reason, you happen to know that myVehicle does in fact refer to a Car, you can use the type cast (Car)myVehicle to tell the computer to treat myVehicle as if it were actually of type Car. So, you could say

myCar = (Car)myVehicle;

and you could even refer to ((Car)myVehicle).numberOfDoors (if numberOfDoors were marked public). As an example of how this could be used in a program, suppose that you want to print out relevant data about a vehicle. You could say:

           Console.WriteLine("Vehicle Data:");
           Console.WriteLine("Registration number:  " 
                                         + myVehicle.registrationNumber);
           if (myVehicle is Car) {
              Console.WriteLine("Type of vehicle:  Car");
              Car c;
              c = (Car)myVehicle;
              Console.WriteLine("Number of doors:  " + c.numberOfDoors);
           }
           else if (myVehicle is Truck) {
              Console.WriteLine("Type of vehicle:  Truck");
              Truck t;
              t = (Truck)myVehicle;
              Console.WriteLine("Number of axels:  " + t.numberOfAxels);
           }
           else if (myVehicle is Motorcycle) {
              Console.WriteLine("Type of vehicle:  Motorcycle");
              Motorcycle m;
              m = (Motorcycle)myVehicle;
              Console.WriteLine("Has a sidecar:    " + m.hasSidecar);
           }

Note that for object types, when the computer executes a program, it checks whether type-casts are valid. So, for example, if myVehicle refers to an object of type Truck, then the type cast (Car)myVehicle will produce an error.