"Converting" between base class and derived class types Relationship between base class and derived class types Fact of inheritance: A class A that is derived (inherits) from another class B inherits: All variables All (ordinary or non-constructor) methods Example: Base class:
public class GeometricObject
{
public String color;
public boolean isFilled;
// Constructors OMITTED...
public String getColor()
{
return color;
}
public boolean getFilled()
{
return isFilled;
}
}
Derived class:
public class Circle extends GeometricObject
{
// Circle inherits from the GeometricObject class,
//
// the variables: color and isFilled
// and the methods: getColor() and getFilled()
//
// are defined in this class !!!
public double radius;
// Constructors OMITTED
public double area() // Ordinary method
{
return Math.PI * radius * radius;
}
}
Objects of the base class and of the derived class: A Circle object contains all members of a GeometricObject object: Conclussion: An object of the base class and derived class has many members in common I.e.: The base class and its derived class are related !!!! "Converting" between base class and derived class types Special privilage given to base class and its derived class data types in Object Oriented Programming: Due to the fact that objects of the base class and derived class share common members: Object Oriented Programming languages allow user to copy (assignment statement) the reference values between base class and derived class object reference variables In other words, Java permits you to perform the following assignment statements:
GeometricObject x ;
Circle y;
Convertion statements:
x = (GeometricObject) y;
y = (Circle) x; // This is "dangerous", discussed later...
Pre-requisite: Operation of the Java compiler Pre-requisite to understand the rest of the material: The only way to use a object reference variable is to select a variable or a method. Example:
GeometricObject x; // Object reference variable
How to use x:
x.color
x.getColor()
The Java compiler will process a class definition first That's because the Java compiler needs to know what variables are contained by the class so it can reserve the precise amount of memory space when an object is created After processing a class definition, the Java compiler will record the members (variables and methods) in the class The Java compiler will use the information to determine if some selected member is legal or illegal Example:
GeometricObject x; // Object reference variable
Legal expressions:
x.color
x.isFilled
x.getColor()
x.getFilled()
Illegal expressions:
x.radius
Example: When we create an object as follows:
GeometricObject x = new GeometricObject() ;
we establish the following correspondence between what is legal and what is available: Because x's data type is a GeometricObject, the following is legal:
x.color
x.isFilled
x.getColor()
x.getFilled()
(i.e., the Java compiler will permit us to write these expressions) Because x points to a GeometricObject, each of the members:
color
isFilled
getColor()
getFilled()
are also available: The error scenario that can be caused by class conversion Important safety rule: Every legal member that you can use must be available Reason: Any legal member can potentially be used in the program If some legal member is not available, then the program execution will cause runtime error (i.e., program will crash) Analogy: You drive on a road and see this sign: According to the sign, it is legal to: Make a left turn Make a right turn Then: You must have a road available in the left direction You must have a road available in the right direction This would be a disaster waiting to happen: Sign says you can turn left, but there is no road !!! You will get in such a situation when you convert between base class and derived class variables ! The effect of assigning a derived class reference to a base class variable (upcasting) The following diagrams illustrate the effect of the assignment:
GeometricObject x = new GeometricObject();
Circle y = new Circle();
x = (GeometricObject) y ;
// Copies a reference of the derived type
// to a base type variable
Effect: Before we perform the assignment x = (GeometricObject) y: Notice that: x is a base class type variable, defined as:
GeometricObject x ;
Because the data type of x is GeometricObject, the following expressions are legal (allowed):
x.color
x.isFilled
x.getColor()
x.getFilled()
After we perform the assignment x = y: Notice that:
x.color is the same variable as y.color
x.isFilled is the same variable as y.isFilled
x.getColor() is the same method as y.getColor()
x.getFilled() is the same method as y.getFilled()
Conclusion: All legal members are available This is safe !!! Note also: The members radius and area() are available But, the Java compiler disallows their access !!! Because the expressions
x.radius
x.area()
are considered illegal by the Java compiler Conclusion: Upcasting will cripple the ability of a derived class object (Some of the members that are available in the object is no longer accessible) Good news: You cannot perform any invalid accesses In other words: Upcasting is safe Programming note Programming note: Because upcasting is safe, the Java compiler permits you to omit the casting operation Example:
public static void main(String[] args)
{
GeometricObject x = new GeometricObject( "Red", true );
// Color of this object is "Red"
Circle y = new Circle ( 5 );
// Color of this object is "Blank"
System.out.println("Before x = y:");
System.out.println("x.color = " + x.color);
System.out.println("x.getColor() = " + x.getColor());
x = y; // Upcasting (no need to use (GeormetricObject) casting
System.out.println("\nAfter x = y:");
System.out.println("x.color = " + x.color);
System.out.println("x.getColor() = " + x.getColor());
}
Output:
Before x = y:
x.color = Red
x.getColor() = Red
After x = y:
x.color = BLANK // x clearly points to the Circle y !
x.getColor() = BLANK
Example Program: (Demo above code) The GeometricObject.java Prog file: click here the Circle.java Prog file: click here The test Prog file: click here How to run the program: Right click on link(s) and save in a scratch directory To compile: javac testProg.java To run: java testProg The effect of assigning a base class reference to a derived class variable (downcasting) The following diagrams illustrate the effect of the assignment:
y = (Circle) x ;
// Copies a reference of the base type (x)
// to a derived type variable
Effect: Before we perform the assignment x = y: Notice that: y is a derived class type variable, defined as:
Circle y ;
Because the data type of y is Circle, the legal expressions are:
Not only:
y.color
y.isFilled
y.getColor()
y.getFilled()
y.radius
y.area()
Therefore, IF we perform the assignment y = (Circle) x, we will have this dangerous situation Notice we can find the following members:
y.color is the same variable as x.color
y.isFilled is the same variable as x.isFilled
y.getColor() is the same method as x.getColor()
y.getFilled() is the same method as x.getFilled()
However: The following legal members are not available in a GeometricObject:
x.radius
x.area()
The result is this dangerous scenario: (Using x.radius is OK, but the variable radius is not available !!!) Therefore: In Java, you cannot assign a base class reference value to a derived class variable !!!! Example:
public static void main(String[] args)
{
GeometricObject x = new GeometricObject( "Red", true );
// Color of this object is "Red"
Circle y = new Circle ( 5 );
// Color of this object is "Blank"
y = (Circle) x; // Illegal !!!
}
Output:
>> java testProg2a
Exception in thread "main" java.lang.ClassCastException:
GeometricObject cannot be cast to Circle
at testProg2a.main(testProg2a.java:12)
Example Program: (Demo above code) The GeometricObject.java Prog file: click here the Circle.java Prog file: click here Prog file: click here How to run the program: Right click on link(s) and save in a scratch directory To compile: javac testProg2a.java To run: java testProg2a "Recovering" a child class reference Wait a minute.... Didn't you say that you can perform the following assignments:
x is a base class typed variable
y is a derived class typed variable
x = (BaseClass) y;
y = (DerivedClass) x; // This is "dangerous", discussed later...
But you also say that: In Java, you cannot assign a base class reference value to a derived class variable !!!! So are you lying when you say that:
y = (DerivedClass) x ; // is this allowed ????
y = a derived class typed variable
x = a base class typed variable
Answer: No, I am no lying, because: Because the variable x can contain a derived class reference value !!!! (In this case, the conversion is allowed !!!) IF x contains a derived class reference value, THEN the assignment:
y = (derived class) x; // is allowed, but must use casting
// to tell the Java compiler that you know
// the danger
x is a base class typed variable
y is a derived class typed variable
(derived class) is a casting operation
Example:
public static void main(String[] args)
{
GeometricObject x = new GeometricObject( "Red", true );
// x is pointing to a base class object
Circle z = new Circle ( 5 );
// z is pointing to a derived class object
// The statement:
//
// y = (Circle) x;
//
// is illegal WHEN x points to a base class object
//
x = z; // x NOW points to a derived class type object !!
y = (Circle) x; // This is legal !!!
}
Example Program: (Demo above code) The GeometricObject.java Prog file: click here the Circle.java Prog file: click here The test Prog file: click here How to run the program: Right click on link(s) and save in a scratch directory To compile: javac testProg2.java To run: java testProg2 The instanceof boolean operator Recall: In Java, you cannot assign a base class reference value to a derived class variable !!!! Helpful operator: To prevent the assignment of a base class reference value to a derived class variable, Java has the instanceof operator that tells you what type of object a reference variable is pointing to:
objRefVar instanceof ClassName
returns: true if objRefVar points to an object of the type ClassName false, otherwise. Example usage:
public static void main(String[] args)
{
GeometricObject x = new GeometricObject( "Red", true );
// x is pointing to a base class object
Circle z = new Circle ( 5 );
// z is pointing to a derived class object
if ( x instanceof Circle )
{
y = (Circle) x; // Will NOT be executed
}
x = z; // x NOW points to a derived class type object !!
if ( x instanceof Circle )
{
y = (Circle) x; // Will be executed
}
}
Example Program: (Demo above code) The GeometricObject.java Prog file: click here the Circle.java Prog file: click here The test Prog file: click here How to run the program: Right click on link(s) and save in a scratch directory To compile: javac testProg3.java To run: java testProg3