+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Upcasting, downcasting

  1. #1
    Sinipull's Avatar
    Sinipull is offline Programming Expert
    Join Date
    Jun 2009
    Location
    Tallinn, Estonia, Estonia
    Posts
    382
    Rep Power
    13

    Upcasting, downcasting

    Upcasting and downcasting are important part of Java, which allow us to build complicated programs using simple syntax, and gives us great advantages, like Polymorphism or grouping different objects. Java permits an object of a subclass type to be treated as an object of any superclass type. This is called upcasting. Upcasting is done automatically, while downcasting must be manually done by the programmer, and i'm going to give my best to explain why is that so.

    Upcasting and downcasting are NOT like casting primitives from one to other, and i believe that's what causes a lot of confusion, when programmer starts to learn casting objects.

    Throughout this tutorial i'm going to use Animal hierarchy to explain how class hierarchy works.

    Inheritance



    What we have here, is a simplified version of an Animal Hierarchy. You can see, that Cat and Dog are both Mammals, which extends from Animal, which silently extends from Object. By silently, i mean, that Java automatically extends every class from Object class, which isn't extended from something else, so everything is an Object (except primitives).

    Now, if you ask - is Cat an Object - It doesn't extend Object, it extends Mammal?
    By inheritance Cat gets all the properties its ancestors have. Object is Cat's grandgrandparent, which means Cat is also an Object. Cat is also an Animal and a Mammal, which logically means - if Mammals possess mammary glands and Animals are living beings, then Cat also has mammary glands and is living being.

    What this means for a programmer, is that we don't need to write for every possible Animal, that it has health. We just need to write it once, and every Animal gets it through inheritance.
    Consider the following example:

    Code:
    class Animal {
    	int health = 100;
    }
    
    class Mammal extends Animal { }
    
    class Cat extends Mammal { }
    
    class Dog extends Mammal { }
    
    public class Test {	 
    	 public static void main(String[] args) {
    		 Cat c = new Cat();
    		 System.out.println(c.health);
    		 Dog d = new Dog();
    		 System.out.println(d.health);
    	 }  
    }
    When running the Test class, it will print "100" and "100" to the console, because both, Cat and Dog inherited the "health" from Animal class.

    Upcasting and downcasting

    First, you must understand, that by casting you are not actually changing the object itself, you are just labeling it differently.
    For example, if you create a Cat and upcast it to Animal, then the object doesn't stop from being a Cat. It's still a Cat, but it's just treated as any other Animal and it's Cat properties are hidden until it's downcasted to a Cat again.
    Let's look at object's code before and after upcasting:
    Code:
        Cat c = new Cat();
        System.out.println(c);
        Mammal m = c; // upcasting
        System.out.println(m);
        
        /*
        This printed:
            Cat@a90653
            Cat@a90653
        */
    As you can see, Cat is still exactly the same Cat after upcasting, it didn't change to a Mammal, it's just being labeled Mammal right now. This is allowed, because Cat is a Mammal.

    Note that, even though they are both Mammals, Cat cannot be cast to a Dog. Following picture might make it a bit more clear.


    Although there's no need to for programmer to upcast manually, it's allowed to do.
    Consider the following example:

    Code:
        Mammal m = (Mammal)new Cat();
    is equal to

    Code:
        Mammal m = new Cat();
    But downcasting must always be done manually:

    Code:
        Cat c1 = new Cat();		 
    	Animal a = c1;		 //automatic upcasting to Animal
    	Cat c2 = (Cat) a;    //manual downcasting back to a Cat
    Why is that so, that upcasting is automatical, but downcasting must be manual? Well, you see, upcasting can never fail. But if you have a group of different Animals and want to downcast them all to a Cat, then there's a chance, that some of these Animals are actually Dogs, and process fails, by throwing ClassCastException.
    This is where is should introduce an useful feature called "instanceof", which tests if an object is instance of some Class.
    Consider the following example:

    Code:
        Cat c1 = new Cat();		 
        Animal a = c1;		 //upcasting to Animal
        if(a instanceof Cat){ // testing if the Animal is a Cat
            System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
            Cat c2 = (Cat)a;
        }
    Note, that casting can't always be done in both ways. If you are creating a Mammal, by calling "new Mammal()", you a creating a Object that is a Mammal, but it cannot be downcasted to Dog or Cat, because it's neither of them.
    For example:
    Code:
        Mammal m = new Mammal();
        Cat c = (Cat)m;
    Such code passes compiling, but throws "java.lang.ClassCastException: Mammal cannot be cast to Cat" exception during running, because im trying to cast a Mammal, which is not a Cat, to a Cat.

    General idea behind casting, is that, which object is which. You should ask, is Cat a Mammal? Yes, it is - that means, it can be cast.
    Is Mammal a Cat? No it isn't - it cannot be cast.
    Is Cat a Dog? No, it cannot be cast.
    Important: Do not confuse variables with instances here. Cat from Mammal Variable can be cast to a Cat, but Mammal from Mammal variable cannot be cast to a Cat.

    Cats cant purr, while being labeled something else
    If you upcast an object, it will lose all it's properties, which were inherited from below it's current position. For example, if you cast a Cat to an Animal, it will lose properties inherited from Mammal and Cat. Note, that data will not be lost, you just can't use it, until you downcast the object to the right level.
    Why is it like that? If you have a group of Animals, then you can't be sure which ones can meow() and which ones can bark(). That is why you can't make Animal do things, that are only specific for Dogs or Cats.


    However the problem above is not an obstacle, if you choose to use polymorphism. Polymorphism uses automatic downcast during method calls. I'm not going to go into details with this one, so i'm referring to Polymorphism tutorial by Turk4n: Polymorphism


    Upcasting during method calling

    The beauty of casting is that programmer can make general methods, which can take a lot of different classes as an argument.
    For example:

    Code:
        public static void stroke(Animal a){
            System.out.println("you stroke the "+a);
        }
    This method can have what ever Animal or it's subclass as an argument. For example calling:

    Code:
        Cat c = new Cat();		 
        Dog d = new Dog();		 
        stroke(c); // automatic upcast to an Animal
        stroke(d); // automatic upcast to an Animal
    ..is a correct code.



    however, if you have a Cat, that is currently being held by Animal variable, then this variable cannot be argument for a method, that expects only Cats, even though we currently have a instance of Cat - manual downcasting must be done before that.



    About variables

    Variables can hold instance of objects that are equal or are hierarchically below them. For example Cat c; can hold instances of Cat and anything that is extended from a Cat. Animal can hold Animal, Mammal, etc..
    Remember, that instances will always be upcasted to the variable level.

    "I really need to make a Dog out of my Cat!"

    Well, you can't do it by casting. However, objects are nothing else, but few methods and fields. That means, you can make a new dog out of your Cat's data.

    Let's say you have a Cat class:

    Code:
    class Cat extends Mammal {
        Color furColor;
        int numberOfLives;
        int speed;
        int balance;
        int kittens = 0;
    	  
        Cat(Color f, int n, int s, int b){
            this.furColor = f;
            this.numberOfLives = n;
            this.speed = s;
            this.balance = b;		  
        }	  
    }
    and a Dog class.

    Code:
    class Dog extends Mammal {
        Color furColor;	  
        int speed;
        int barkVolume;
        int puppies = 0;
    	  
        Dog(Color f, int n, int s, int b){
            this.furColor = f;		  
            this.speed = s;
            this.barkVolume = b;		  
        }	  
    }
    and you want to make a Dog out of the Cat. All you need to do, is, place a method inside of the Cat class, that converts the fields and returns a new Dog based on that.

    Code:
        public Dog toDog(int barkVolume){		  
            Dog d = new Dog(furColor, speed, barkVolume);
            d.puppies = kittens;
            return d;		  
        }
    As you can see, they don't match that well, so some fields were inconvertible, and some data had to be made from scratch. Notice, that numberOfLives and Balance were not converted, and barkVolume was completely new data. If you have 2 Classes, that match perfectly, then hurray, but it rarely happens.
    conversion can now be called from where ever you need:

    Code:
        Cat c = new Cat(Color.black, 9, 20, 40);
        Dog d = c.toDog(50);
    Thanks for reading.
    Last edited by Sinipull; 10-19-2009 at 02:55 PM. Reason: some pictures were gone.

  2. CODECALL Circuit advertisement
    Join Date
    Always
    Location
    Advertising world
    Posts
    Many

     
  3. #2
    Join Date
    Jul 2006
    Posts
    16,491
    Blog Entries
    75
    Rep Power
    143

    Re: Upcasting, downcasting

    I like the images. Very nice! +rep
    Programming is a branch of mathematics.
    My CodeCall Blog | My Personal Blog

  4. #3
    ThemePark is offline Programmer
    Join Date
    Oct 2008
    Location
    Århus, Denmark
    Posts
    105
    Rep Power
    0

    Re: Upcasting, downcasting

    I could have really used this a few days ago! Also, I get the feeling that this is made because of my thread. Like WingedPanther said, nice images and nice, understandable tutorial which cleared up a few things for me.

    +rep

  5. #4
    Jordan Guest

    Re: Upcasting, downcasting

    Wow, nice work! The images really are nice. +rep

  6. #5
    Join Date
    Aug 2009
    Location
    ~/
    Posts
    918
    Rep Power
    19

    Re: Upcasting, downcasting

    Awesome, and I'm not a even a Java guy +rep

  7. #6
    Sinipull's Avatar
    Sinipull is offline Programming Expert
    Join Date
    Jun 2009
    Location
    Tallinn, Estonia, Estonia
    Posts
    382
    Rep Power
    13

    Re: Upcasting, downcasting

    Quote Originally Posted by ThemePark View Post
    Also, I get the feeling that this is made because of my thread.
    You are quite right. That's where i got the idea. : )
    Thanks, everybody.

  8. #7
    Join Date
    Jul 2009
    Location
    Santa Clarita, CA
    Posts
    2,111
    Blog Entries
    47
    Rep Power
    31

    Re: Upcasting, downcasting

    A lot of work went in to this, really high quality! Great tutorial!

    +rep
    Wow I changed my sig!

  9. #8
    ssabrewolf is offline Newbie
    Join Date
    Nov 2009
    Posts
    1
    Rep Power
    0

    Re: Upcasting, downcasting

    Jajaa very creative, thank you for all the effort you invested on it , i was looking for an automated downcasting way, i mean, if i have an ancestor with say n=100 propertys and its subclasses has n+m propertys , is there any mean to initialize the first n propertys from an already constructed superclass object? one posible solution its throug dynamic call to java methods, but this is prone to errors and design holes in a production enviroment

  10. #9
    Join Date
    Aug 2007
    Location
    Gizeh, Al Jizah, Egypt, Egypt
    Posts
    8,675
    Blog Entries
    12
    Rep Power
    81

    Re: Upcasting, downcasting

    well done.
    you deserve more +rep
    i like the images, really neat
    yo homie i heard you like one-line codes so i put a one line code that evals a decrypted one line code that prints "i love one line codes"
    Code:
    eval(base64_decode("cHJpbnQgJ2kgbG92ZSBvbmUtbGluZSBjb2Rlcyc7"));
    www.amrosama.com | the unholy methods of javascript

  11. #10
    Sinipull's Avatar
    Sinipull is offline Programming Expert
    Join Date
    Jun 2009
    Location
    Tallinn, Estonia, Estonia
    Posts
    382
    Rep Power
    13

    Re: Upcasting, downcasting

    is there any mean to initialize the first n propertys from an already constructed superclass object?
    I don't think that's possible. I think you need some conversion method, which initializes all the fields. But if you find a shortcut, then let me know

+ Reply to Thread
Page 1 of 2 12 LastLast

Thread Information

Users Browsing this Thread

There are currently 5 users browsing this thread. (0 members and 5 guests)

Similar Threads

  1. about casting/downcasting
    By John Jang in forum Java Help
    Replies: 2
    Last Post: 05-16-2011, 04:24 AM
  2. about casting/downcasting
    By John Jang in forum C and C++
    Replies: 0
    Last Post: 05-15-2011, 06:32 PM

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts