Upcasting:   assigning an instance of a subclass to a variable of a superclass

  • Upcasting = cast (= assign) an instance of a subclass to a variable of a superclass

    I.e.:

        Superclass a;
    
    
        a = new Subclass(); // An upcasting operation

    Graphically:

Upcasting:   assigning an instance of a subclass to a variable of a superclass

  • You can also achieve upcasting by assigning a subclass variable to a superclass variable:

    Example:

        Superclass a;
        Subclass   b = new Subclass();
    
        a = b;        // Upcasting

    Graphically:

Upcasting:   assigning an instance of a subclass to a variable of a superclass

  • Upcasting is allowed because a subclass object can perform all actions that you can request using a superclass typed variable:

    Graphically:

  • Because a subclass object contains a superclass object, it can perform all actions that are defined inside a superclass type

Upcasting example and demo   compile and run in BlueJ

public class myProg
{
    public static void main(String[] args)
    {
        GeometricObject a;
        Circle b = new Circle("red", 1);
        
        a = b;  // Upcasting
        
        System.out.println(a.getArea());
    }
}

  
public class GeometricObject
{
    private String color;

    GeometricObject( String col )   // Constructor
    {
        color = col;
    }

    public String getColor()          { return color; }
    public void   setColor(String c)  { color = c; }   

    public double getArea()  // Dummy method !!
    {
        return 0;  // Some default value
    }
} 
public class Circle extends GeometricObject
{
    private double radius;


    Circle(String col, double r)
    {
        super(col);
        radius = r;
    }

    public double getRadius()         
    { 
        return radius;
    }

    public double getArea()
    {
        return 3.14159*radius*radius;
    }

    public String toString()
    {
        return "Color = " + getColor() + ":"
                + "radius = " + radius;
    }
}
public class Rectangle extends GeometricObject
{

    private double width;
    private double height;

    Rectangle(String col, double w, double h)
    {
        super(col); width = w; height = h;
    }

    public double getWidth()          { return width;}
    public void   setWidth(double r)  { width = r; }
    public double getHeight()         { return height;}
    public void   setHeight(double r) { height = r; }

    public double getArea()       
    {
        return width*height;
    }
    
    public String toString()
    {
        return "Color = " + getColor() + ":"
                + "width = " + width
                + " height = " + height;
    }
} 

Downcasting:   assigning an instance of a superclass to a variable of a subclass

  • Downcasting = cast (= assign) an instance of a superclass to a variable of a subclass

    I.e.:

    
        Subclass b;
    
        b = new Superclass(); // A downcasting operation

    Graphically:

Downcasting:   assigning an instance of a superclass to a variable of a subclass

  • You can also achieve downcasting by assigning a superclass variable to a subclass variable:

    Example:

        Superclass a = new Superclass();
        Subclass b; 
    
        b = a;        // Downcasting

    Graphically:

Downcasting:   assigning an instance of a superclass to a variable of a subclass

  • Downcasting is not allowed because a superclass object may not be able to perform all actions that you can request using a subclass typed variable:

    Graphically:

    Because a subclass object contains a superclass object, it can perform all actions that are defined inside a superclass type

Downcasting example and demo   compile and see error message in BlueJ

public class myProg
{
    public static void main(String[] args)
    {
        GeometricObject a
                  = new GeometricObject("red");
        Circle b;
        
        b = a;  // Downcasting
                // Compile error !! (Illegal !)
    }
}
 
public class GeometricObject
{
    private String color;

    GeometricObject( String col )   // Constructor
    {
        color = col;
    }

    public String getColor()          { return color; }
    public void   setColor(String c)  { color = c; }   

    public double getArea()  // Dummy method !!
    {
        return 0;  // Some default value
    }
} 
public class Circle extends GeometricObject
{
    private double radius;


    Circle(String col, double r)
    {
        super(col);
        radius = r;
    }

    public double getRadius()         
    { 
        return radius;
    }

    public double getArea()
    {
        return 3.14159*radius*radius;
    }

    public String toString()
    {
        return "Color = " + getColor() + ":"
                + "radius = " + radius;
    }
}
public class Rectangle extends GeometricObject
{

    private double width;
    private double height;

    Rectangle(String col, double w, double h)
    {
        super(col); width = w; height = h;
    }

    public double getWidth()          { return width;}
    public void   setWidth(double r)  { width = r; }
    public double getHeight()         { return height;}
    public void   setHeight(double r) { height = r; }

    public double getArea()       
    {
        return width*height;
    }
    
    public String toString()
    {
        return "Color = " + getColor() + ":"
                + "width = " + width
                + " height = " + height;
    }
} 

Legal downcasting operations

  • However.... there are situations where downcasting is legal (and neccessary)

  • The most common situation is:

      1. We performed an upcasting operation (which restricted the actions we can perform on a subclass object)

      2. Later, we need to perform an action that is defined in the subclass

  • Example:

          public static void main(String[] args)
          {
              GeometricObject a = new Circle("red", 1); 
                                                 // (1) Upcasting
      
              System.out.println(a.getArea());
              
              System.out.println(a.getRadius()); // (2) Error ! 
          }

    We cannot invoke getRadius() using a GeometricObject variable a !! (Demo)

Legal downcasting operations

  • How to perform a legal downcasting operation:

          public static void main(String[] args)
          {
              GeometricObject a = new Circle("red", 1); 
                                                // Upcasting
      
              System.out.println(a.getArea());
              
      	Circle b;
      
      	b = (Circle) a;
      
              System.out.println(a.getRadius()); // Error ! 
          }

    (0) The variable a ( GeometricObject type) does not have a getRadius() method

Legal downcasting operations

  • How to perform a legal downcasting operation:

          public static void main(String[] args)
          {
              GeometricObject a = new Circle("red", 1); 
                                                // Upcasting
      
              System.out.println(a.getArea());
             
      	Circle b;
       
      	b = (Circle) a;
      
              System.out.println(b.getRadius()); // OK ! 
          }

    (1) We must use a Circle typed variable to invoke the getRadius() method

Legal downcasting operations

  • How to perform a legal downcasting operation:

          public static void main(String[] args)
          {
              GeometricObject a = new Circle("red", 1); 
                                                // Upcasting
      
              System.out.println(a.getArea());
             
      	Circle b;
       
      	b = (Circle) a;                    // Explicit upcasting
      
              System.out.println(b.getRadius()); // OK ! 
          }

    (2) We cast the reference in a to a Circle reference with the downcasting operation (Circle)

    Demo

Downcasting operation depends on the subclass type object

  • How to downcast an upcasted Rectangle object:

          public static void main(String[] args)
          {
              GeometricObject a = new Rectangle("red", 1, 2); 
                                                // Upcasting
      
              System.out.println(a.getArea());
             
      	Rectangle b;
       
      	b = (Rectangle) a;                // Downcasting
      
              System.out.println(b.getWidth()); 
              System.out.println(b.getHeight()); 
          }

    We must downcast the subclass object to the correct subclass type variable !!!


    Question:  

      • What if we do not know the subtype when we perform the downcast operation??

Downcasting a subtype object of unknown subclass type

  • Problem:   suppose the superclass variable references to a subclass object of unknown subclass type:

        public static void main(String[] args)
        {
            GeometricObject a = (can be  a Circle or Rectangle object)
                                // Upcasting
    
            if ( a is a Circle )
    	   print its radius
    	else if ( a is a Rectangle )
    	   print its width and height
            else
    	   print "invalid subclass type"
        }
      

    How can we write the above program ??

The instanceof boolean condition

  • Java has the instanceof boolean operator that test if the referenced object is of a certain class

  • Syntax:

        objectRefVar instanceof className
    
             Returns true if the object referenced to by
    	 objectRefVar is a className object
      
             Otherwise, returns false

  • Example:

        if ( a instanceof Circle )
            System.out.println("a is a Circle");
    

How to downcasting a subtype object of unknown subclass type

We can perform the correct downcast operation based on the subclass type of the object referenced by a:

    public static void main(String[] args)
    {
        GeometricObject a = (can be  a Circle or Rectangle object)
                            // Upcasting

        if ( a is a Circle )
	{


	    print its radius
	}
	else if ( a is a Rectangle )
	{


	    print its width and height

	}
        else
	    print "invalid subclass type"
    }
  

How to downcasting a subtype object of unknown subclass type

If a references to a Circle object, then downcast (convert) to a Circle variable:

    public static void main(String[] args)
    {
        GeometricObject a = (can be  a Circle or Rectangle object)
                            // Upcasting

        if ( a instanceof Circle )
	{
	    Circle b = (Circle) a; // Downcast to a Circle

	    System.out.println(b.getRadius());
	}
	else if ( a is a Rectangle )
	{


	    print its width and height

	}
        else
	    print "invalid subclass type"
    }
  

How to downcasting a subtype object of unknown subclass type

If a references to a Rectangle object, then downcast (convert) to a Rectangle variable:

    public static void main(String[] args)
    {
        GeometricObject a = (can be  a Circle or Rectangle object)
                            // Upcasting

        if ( a instanceof Circle )
	{
	    Circle b = (Circle) a; // Downcast to a Circle

	    System.out.println(b.getRadius());
	}
	else if ( a instanceof Rectangle  )
	{
	    Rectangle b = (Rectangle) a; // Downcast to a Rectangle

	    System.out.println(b.getWidth());
	    System.out.println(b.getHeight());
	}
        else
	    print "invalid subclass type"
    }
  

How to downcasting a subtype object of unknown subclass type

Otherwise (it can be a GeometricObject !), print the warning message:

    public static void main(String[] args)
    {
        GeometricObject a = (can be  a Circle or Rectangle object)
                            // Upcasting

        if ( a instanceof Circle )
	{
	    Circle b = (Circle) a; // Downcast to a Circle

	    System.out.println(b.getRadius());
	}
	else if ( a instanceof Rectangle  )
	{
	    Rectangle b = (Rectangle) a; // Downcast to a Rectangle

	    System.out.println(b.getWidth());
	    System.out.println(b.getHeight());
	}
        else
	    System.out.println("Invalid subclass type");
    }
  

Demo