bob
bob

Reputation: 1889

Why do you need to list two object types when you instantiate an object?

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

Answers (6)

Richard JP Le Guen
Richard JP Le Guen

Reputation: 28753

what are the object types of cat1, cat2, cat3, cat4, and cat5?

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.

  • The declared type of cat1 is JungleCat; the run-time type of cat1 is also JungleCat
  • The declared type of cat2 is Cat; the run-time type of cat2 is also Cat
  • The declared type of cat3 is Cat; the run-time type of cat3 is JungleCat
  • The declared type of cat4 is JungleCat; the run-time type of cat4 is Cat
    • Yes, this is illegal. Without an explicit downcast it won't compile; with an explicit cast... it might but it'll throw an exception at run-time.
  • The declared type of 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

Rohit Jain
Rohit Jain

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

Yuushi
Yuushi

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

Subin Sebastian
Subin Sebastian

Reputation: 10997

When you instantiate an Object you have to specify

  1. what is the reference type or type(class) your new variable is capable of referring to
  2. to initialize an Object we need to specify the type(class) of the object

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

Kumar Vivek Mitra
Kumar Vivek Mitra

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

Azodious
Azodious

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

Related Questions