Anda di halaman 1dari 9

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 im 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 thats what causes a lot of
confusion, when programmer starts to learn casting objects.
Throughout this tutorial im going to use !nimal hierarchy to explain how class hierarchy works.
"hat we have here, is a simplified version of an !nimal #ierarchy. $ou can see, that %at and &og are both 'ammals,
which extends from !nimal, which silently extends from (bject. )y silently, i mean, that Java automatically extends
every class from (bject class, which isnt extended from something else, so everything is an (bject *except primitives+.
,ow, if you ask - is %at an (bject - .t doesnt extend (bject, it extends 'ammal/
)y inheritance %at gets all the properties its ancestors have. (bject is %ats grandgrandparent, which means %at is also an
(bject. %at is also an !nimal and a 'ammal, which logically means - if 'ammals possess mammary glands and !nimals
are living beings, then %at also has mammary glands and is living being.
"hat this means for a programmer, is that we dont need to write for every possible !nimal, that it has health. "e just
need to write it once, and every !nimal gets it through inheritance.
%onsider the following example0
class !nimal 1
int health 2 3445
class 'ammal extends !nimal 1 6
class %at extends 'ammal 1 6
class &og extends 'ammal 1 6
public class Test 1
public static void main*7tring89 args+ 1
%at c 2 new %at*+5
&og d 2 new &og*+5
"hen running the Test class, it will print :344: and :344: to the console, because both, %at and &og inherited the :health:
from !nimal class.
Upcasting and downcasting
;irst, you must understand, that by casting you are not actually changing the object itself, you are just labeling it
;or example, if you create a %at and upcast it to !nimal, then the object doesnt stop from being a %at. .ts still a %at, but
its just treated as any other !nimal and its %at properties are hidden until its downcasted to a %at again.
<ets look at objects code before and after upcasting0
%at c 2 new %at*+5
'ammal m 2 c5 == upcasting

This printed0
!s you can see, %at is still exactly the same %at after upcasting, it didnt change to a 'ammal, its just being labeled
'ammal right now. This is allowed, because %at is a 'ammal.
,ote that, even though they are both 'ammals, %at cannot be cast to a &og. ;ollowing picture might make it a bit more
!lthough theres no need to for programmer to upcast manually, its allowed to do.
%onsider the following example0
'ammal m 2 *'ammal+new %at*+5
is eDual to
'ammal m 2 new %at*+5
)ut downcasting must always be done manually0
%at c3 2 new %at*+5
!nimal a 2 c35 ==automatic upcasting to !nimal
%at cE 2 *%at+ a5 ==manual downcasting back to a %at
"hy is that so, that upcasting is automatical, but downcasting must be manual/ "ell, you see, upcasting can never fail.
)ut if you have a group of different !nimals and want to downcast them all to a %at, then theres a chance, that some of
these !nimals are actually &ogs, and process fails, by throwing %lass%astFxception.
This is where is should introduce an useful feature called :instanceof:, which tests if an object is instance of some %lass.
%onsider the following example0
%at c3 2 new %at*+5
!nimal a 2 c35 ==upcasting to !nimal
if*a instanceof %at+1 == testing if the !nimal is a %at
7ystem.out.println*:.ts a %atG ,ow i can safely downcast it to a %at, without a fear of failure.:+5
%at cE 2 *%at+a5
,ote, that casting cant always be done in both ways. .f you are creating a 'ammal, by calling :new 'ammal*+:, you a
creating a (bject that is a 'ammal, but it cannot be downcasted to &og or %at, because its neither of them.
;or example0
'ammal m 2 new 'ammal*+5
%at c 2 *%at+m5
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
eneral idea behind casting, is that, which object is which. !ou should as", is Cat a Mammal# !es,
it is $ that means, it can be cast.
%s Mammal a Cat# &o it isn't $ it cannot be cast.
%s Cat a (og# &o, it cannot be cast.
%mportant: (o not con)use variables with instances here. Cat )rom Mammal *ariable can be cast
to a Cat, but Mammal )rom Mammal variable cannot be cast to a Cat.
Cats cant purr, while being labeled something else
%) you upcast an object, it will lose all it's properties, which were inherited )rom below it's current
position. +or example, i) you cast a Cat to an ,nimal, it will lose properties inherited )rom
Mammal and Cat. &ote, that data will not be lost, you just can't use it, until you downcast the
object to the right level.
-hy is it li"e that# %) you have a group o) ,nimals, then you can't be sure which ones can meow./
and which ones can bar"./. 0hat is why you can't ma"e ,nimal do things, that are only speci1c
)or (ogs or Cats.
2owever the problem above is not an obstacle, i) you choose to use polymorphism.
3olymorphism uses automatic downcast during method calls. %'m not going to go into details with
this one, so i'm re)erring to 3olymorphism tutorial by 0ur"4n: 3olymorphism
Upcasting during method calling
0he beauty o) casting is that programmer can ma"e general methods, which can ta"e a lot o)
di5erent classes as an argument.
+or example:
public static void stroke*!nimal a+1
7ystem.out.println*:you stroke the :Ha+5
This method can have what ever !nimal or its subclass as an argument. ;or example calling0
%at c 2 new %at*+5
&og d 2 new &og*+5
stroke*c+5 == automatic upcast to an !nimal
stroke*d+5 == automatic upcast to an !nimal a correct code.
however, if you have a %at, that is currently being held by !nimal variable, then this variable cannot be argument for a
method, that expects only %ats, even though we currently have a instance of %at - manual downcasting must be done
before that.
About variables
Iariables can hold instance of objects that are eDual or are hierarchically below them. ;or example %at c5 can hold
instances of %at and anything that is extended from a %at. !nimal can hold !nimal, 'ammal, etc..
Jemember, that instances will always be upcasted to the variable level.
"I really need to make a Dog out o my !at""
"ell, you cant do it by casting. #owever, objects are nothing else, but few methods and fields. That means, you can make
a new dog out of your %ats data.
<ets say you have a %at class0
class %at extends 'ammal 1
%olor fur%olor5
int number(f<ives5
int speed5
int balance5
int kittens 2 45

%at*%olor f, int n, int s, int b+1
this.fur%olor 2 f5
this.number(f<ives 2 n5
this.speed 2 s5
this.balance 2 b5
and a &og class.
class &og extends 'ammal 1
%olor fur%olor5
int speed5
int barkIolume5
int puppies 2 45

&og*%olor f, int n, int s, int b+1
this.fur%olor 2 f5
this.speed 2 s5
this.barkIolume 2 b5
and you want to make a &og out of the %at. !ll you need to do, is, place a method inside of the %at class, that converts the
fields and returns a new &og based on that.
public &og to&og*int barkIolume+1
&og d 2 new &og*fur%olor, speed, barkIolume+5
d.puppies 2 kittens5
return d5
!s you can see, they dont match that well, so some fields were inconvertible, and some data had to be made from scratch.
,otice, that number(f<ives and )alance were not converted, and barkIolume was completely new data. .f you have E
%lasses, that match perfectly, then hurray, but it rarely happens.
conversion can now be called from where ever you need0
%at c 2 new %at*, @, E4, K4+5
&og d 2*B4+5
Thanks for reading.
Jead more0 Java Upcasting, downcasting