Reputation: 1889
If I have JungleCat as a subclass of Cat (JungleCat extends Cat), and then I say:
JungleCat cat1 = new JungleCat();
Cat cat2 = new Cat();
Cat cat3 = new JungleCat();
JungleCat cat4 = new Cat(); //this one is illegal, right?
JungleCat cat5;
I'm wondering what are the object types of cat1
, cat2
, cat3
, cat4
, and cat5
? I'm also wondering why there's redundancy in instantiating an object: why do you need to list two object types when you instantiate an object.
I'm sorry if this is a really basic question, but it's the sort of thing where I just want to know once and for all and with a good answer with good reasoning, which I know I can expect here (and not Yahoo Answers, etc) :P
Upvotes: 5
Views: 232
Reputation: 28753
what are the object types of
cat1
,cat2
,cat3
,cat4
, andcat5
?
I don't know what "object type" means in this context. I'd recommend instead thinking of things in terms of declared type and run-time type.
cat1
is JungleCat
; the run-time type of cat1
is also JungleCat
cat2
is Cat
; the run-time type of cat2
is also Cat
cat3
is Cat
; the run-time type of cat3
is JungleCat
cat4
is JungleCat
; the run-time type of cat4
is Cat
cat5
is JungleCat
; it has no run-time type.The point of the "redundancy" is because Java is statically typed and also supports dynamic dispatching. The static typing requires that variables have a declared type; the dynamic dispatching allows the run-time type to be different from the declared type.
For example, you could assign more than one object to the same variable during the course of your program's execution:
Cat c1 = new Cat();
c1 = new JungleCat();
The declared type of c1
determines what methods can be invoked via that variable:
Cat c1 = new Cat();
c1.purr(); // compiles without error
c1 = new JungleCat();
c1.purr(); // compiles without error
Likewise it determines what methods cannot be invoked via that variable:
JungleCat jc1 = new JungleCat();
Cat c1 = jc1;
jc1.roar(); // compiles without error - JungleCats can roar!
c1.roar(); // compile error! Cats don't roar
This allows a variable's behavior to vary by run-time type - polymorphism - while still having compile time checking.
Upvotes: 2
Reputation: 213261
In the below statement: -
JungleCat cat1 = new JungleCat();
You can break it up in two parts: -
JungleCat cat1; // This creates a reference of type `JungleCat`
cat1 = new JungleCat(); // This creates an object of type `JungleCat`.
Now, you are making the cat1
reference, point to the JungleCat
object. References are nothing but a link to the object that is created, so that you can access them.
You can also create object just like this: -
new JungleCat(); // Will create an unnamed object
But, in the above case, you will only be able to use the methods and properties at the place where you have instantiated. But, later on, since you have no reference to access that object, you can't access it's properties either.
Now, let's move ahead to the 2nd statement: -
Cat cat = new JungleCat();
Here, as you can guess, you have reference of type Cat - Super Class
, and an object of type JungleCat
. This is what we call Polymorphism
.
So, basically, you can create a reference of any super type, and make it point to an object of any subtype. This is pretty simple to understand - "Since a JungleCat is a Cat only. So, you can always have a Cat reference point to JungleCat".
This is not true the other way round. For e.g.: -
JungleCat ref = new Cat();
Now this is not valid. Because a Cat
is not neccessarily a JungleCat
. It can be any other Cat. So, you can't have your JungleCat
reference point to a Cat
object.
Now here's your actual concern: -
I'm wondering what are the object types of cat1, cat2, cat3, cat4, and cat5
Well, cat1
, cat2
.. are not objects, but are references pointing to some objects. And you can infer from the above explanation, the reference type of each of them.
Object types are the type used on the RHS of the object creation statement. The type used with new
keyword, is the type of the Object
. You can have different types of reference pointing to the same object type.
So, you can have both cat1
, and cat2
references pointing to the same object type.
Upvotes: 5
Reputation: 26040
This is the fundamental principle behind polymorphism. The type of each object is what appears on the left hand side of the expression, however, it will act like whatever is on the right hand side. For example, let's think of a function like so:
public static void Claw(Cat cat)
{
cat.claw();
}
Now, we assume our classes are something like:
public class Cat
{
//...
public void claw()
{
System.out.println("Cat claw");
}
}
public class JungleCat extends Cat
{
//...
@Override
public void claw()
{
System.out.println("Jungle cat claw");
}
}
Now, let's instanstiate some objects:
Cat c = new Cat();
Cat j = new JungleCat();
Passing into our static Claw
function:
Claw(c); //Prints "Cat claw"
Claw(j); //Prints "Jungle cat claw"
Assume we modified the function like so:
public static void Claw(JungleCat junglecat)
{
junglecat.claw();
}
Then Claw(c)
will obviously not compile, as it's a Cat
. What about Claw(j)
? This also won't compile, as we've said it's also of type Cat
. We know that it's actually a JungleCat
, but we've told the compiler "ok, just treat this like it's a normal Cat
type".
What's often missing in a lot of these beginner examples is motivation as for why someone would want to do this. Cats and Animals and the like are often poor examples. For a better example, suppose we have some code which is meant to do different things based on what operating system it's running on; say moving a file around. If it runs on Linux
, we want to move a file to /usr/bin
say, if it's on Windows, C:\Windows\System32
. So we define an interface like so:
public interface FileMover
{
public void move(File f);
}
public class LinuxMover implements FileMover
{
public void move(File f)
{
//Move our file to /usr/bin
}
}
public class WindowsMover implements FileMover
{
public void move(File f)
{
//Move our file to C:\Windows\System32
}
}
Now, we don't know which system this code is going to run on until runtime - so we can do a runtime check and instantiate the proper class at runtime:
//Pseudocode
FileMover fm;
if(OperatingSystem == LINUX) {
fm = new LinuxMover();
}
else if(OperatingSystem == WINDOWS) {
fm = new WindowsMover();
}
fm.move();
Likewise, any functions can simply take a FileMover
- they don't care what kind - hence we don't have to write two function definitions every time we want to use a different kind of FileMover
, eg doSomething(WindowsFileMover m)
and doSomething(LinuxFileMover m)
, we can simply replace this with one function doSomething(FileMover m)
, pass in the correct type, and it will "just work".
This is probably a lot more info than the question requires, but hopefully it also gives you some intuition as to why such things are done in a slightly more concrete way than the usual Cats and Dogs.
Upvotes: 0
Reputation: 10997
When you instantiate an Object you have to specify
So basically a you need to create a JungleCat object and also create a reference pointing to it. The reference pointing to it is capable of pointing to Cat(JungleCat, PetCat and all cats) in case of
Cat cat3 = new JungleCat();
and only JungleCats if
JungleCat cat3 = new JungleCat();
About
object types of cat1, cat2, cat3, cat4, and cat5?
Object types will be what you are assigning to it from right hand side of assignment operater.
About
JungleCat cat4 = new Cat(); //this one is illegal, right?
Yes because, a cat need not be a JungleCat(only thing we know about it is that, it is a cat), but a JungleCat is a cat for sure. Thats why
Cat cat= new JungleCat();
is valid
Upvotes: 2
Reputation: 33534
- Polymorphism
work as the Object of sub-class is assigned to the Object Reference Variable of the super-class.
- And as this is a class polymorphism
the sub-class must be in the same inheritance tree, and the sub-class must be the of the super-type.
So
Cat c = new JungleCat(); // Will work
But,
JungleCat c = new Cat(); // Won't work
Upvotes: 0
Reputation: 13872
JungleCat cat4 = new Cat(); //this one is illegal, right?
Yes. A derived class reference can't point to it's base class.
I'm wondering what are the object types of cat1, cat2, cat3, cat4, and cat5?
Use getClass
methos to know.
why you need to list two object types when you instantiate an object.
This is called polymorphism
. i.e. one base class reference can point to any of it's derived class.
Upvotes: 0