aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Reference Type vs. Object Type Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Reference Type vs. Object Type" Watch "Reference Type vs. Object Type" New topic
Author

Reference Type vs. Object Type

Tyrel Sackett
Greenhorn

Joined: Oct 23, 2013
Posts: 4

I just failed my first attempt at the Java certification (by one question), and have found a fundamental concept that I'm not sure I completely understand:

Part 1

What exactly is the value of declaring a reference variable of a different type/class than the object type/class?

class Animal {}
class Cat extends Animal {}

Animal a = new Animal();
Cat c = new Cat();
Animal b = new Cat();

What can 'b' do/not do because of this?

Part 2

What would be the value of casting an object (maybe understanding Part 1 will explain)? I saw this exact format on the exam:

class Alpha { void work(); }
class Beta extends Alpha { void work(); }

((Alpha) new Beta()).work();

Part 3

I also saw something like this:

interface Beta {}
class Alpha implements Beta {}

Beta a = new Alpha();

I know you can't do "new Beta()", but I was surprised to get home and try this to find that the reference type can be an interface and couldn't understand why you would do that (I realize the question isn't always "should" you but "can' you ... I also realize that, in a way, an interface is just an fully abstract class, but is there any difference here when declaring a reference variable?).

Thank you for your time and patience
Tina Smith
Ranch Hand

Joined: Jul 21, 2011
Posts: 177
    
    6

The advantage of declaring a variable as a different type than the actual object instance is flexibility.

Let's say I have the following (which is not intended to compile):


If I declare the type to be Animal, I can do the following:


Whereas if I had explicitly defined a Cat and a Dog, I would have to tell each one to speak() individually. That's maybe not an issue for smaller examples, but when working with real code it can be a huge example.
It's also rather handy if you can work with an Animal and you don't have to know that it's a Cat or a Dog, you just know that all animals speak, and perhaps cared for and fed. You can add new Animal types without worrying about breaking existing code because as long as the new Animals are Animal types, you can deal with them.

When working with an instance of an "interface" (I'm saying this because you don't know the class type) it's pretty much the same as working with an abstract class. The only feature advantage you get from an interface is that you can implement a form of "multiple inheritance" (because the Alpha could also implement or extend Gamma. It's not true multiple inheritance because you can only extend the interface from interfaces, whereas you extend functionality from classes).

And welcome to the Ranch!


Everything is theoretically impossible, until it is done. ~Robert A. Heinlein
Tyrel Sackett
Greenhorn

Joined: Oct 23, 2013
Posts: 4

Thanks Tina for the reply (I'm sorry I haven't replied sooner myself ... I never got a notification of your reply for some reason ).

"if I had explicitly defined a Cat and a Dog, I would have to tell each one to speak() individually"

So, I understood what you said, but when I change:

Animal cat = new Cat();
Animal dog = new Dog();

To:

Cat cat = new Cat();
Dog dog = new Dog();

Then a.speak() still prints out "meow" and "woof" ... I can't seem to get examples to work to help myself understand the difference

I was also able to substitute 'class Animal' for 'interface Animal' (implementing the interface instead of extending the class), and it works exactly the same. Can you explain this in a little more detail:

"It's not true multiple inheritance because you can only extend the interface from interfaces, whereas you extend functionality from classes"

I know interfaces can only extend interfaces, and classes can only implement interfaces and extend a single class, so other than using an interface so the class can still extend a class, I guess I'm not sure what you can/can't do by using an interface as the reference type. (or is it simply because you don't know the class type - you only know it implements a particular interface?)

Thanks again (I will watch closer for a reply this time )!
Tina Smith
Ranch Hand

Joined: Jul 21, 2011
Posts: 177
    
    6

For the first one...understanding the difference between declaring the animal as an instance of its supertype....

The main advantage comes in being able to treat all cats and dogs the same, and not having to know which one you're dealing with. Let's expand the example a bit.



So now we have an Animal that knows how to speak, a Cat that IS-A Animal, and also knows how to purr, and a Dog that IS-A Animal and also knows how to walk.

If we write the following, it will fail to compile.



Specifically, cat.purr() and dog.walk() will not compile. Yes, the Cat is a Cat object, but because it's been declared as an Animal, that's all the compiler knows about.
If we were to comment out the purr() and walk() lines, the Cat and Dog would print the Cat and Dog-specific values; meow and woof respectively, not the "abstract speak" from Animal.

So declaring an object as its superclass or interface can restrict what you are able to do with it. Where is the value in this? Well, it's all about generic handling of code. If you need to know that a Cat can purr(), then declare it as a Cat. If all you need to know is that a Cat IS-A Animal, declare it as an Animal.

For a variable that is declared and used directly, this may not seem too useful. However, whenever you want to handle multiple types of Animals at a time without caring what exact type of Animal they are, it becomes a nice to have. Let's look at the following:

So the compiler knows that the list contains Animals only. It has no real idea whether I put Cats, Dogs, Fishes, Butterflies, or any other Animals in that list. What it does know is that the list contains Animals, and that all Animals can speak.

To give a concrete example of how this type of generic handling is useful in the Java libraries, consider networking access:

The object "s" points to an "InputStream" in the same way as the example "cat" points to an "Animal". But you don't need to know about the exact type of s to be able to use it. It's all about the generic handling. Hopefully this explains it a bit more

For interfaces, why wouldn't you define a reference type as an interface? Interfaces do not define what the class is, rather what it can-do. So if you're handling code from the point of view of can-do rather than is-a, why not use an interface as a reference type? Perhaps a more concrete reason to use interfaces is if we decided a Boat class could also speak(). A Boat is obviously not-an Animal, but it can-do the same thing as a Cat. It's a different way of thinking about the code.

Let's change the example up a bit to suit this new world-view. In this example, you can treat a Cat as both an Animal and a Speaker. It's not true multiple inheritance, but it looks like it..... If it were true multiple inheritance, Speaker would be able to define how-to speak rather than just defining a class that can.


There is no difference when declaring a reference variable between a class and an interface, other than the obvious you can't directly instantiate an instance of an interface. If you're being handed a type by some other code and don't have the documentation at hand to tell you, you can't tell whether that type is an interface or a class.

Hopefully the examples help. And welcome to the Ranch!
Tyrel Sackett
Greenhorn

Joined: Oct 23, 2013
Posts: 4

Thank you for the time to respond and for the examples ... I do understand this better now.

Just one last question that maybe you can provide some insight on ... your example:



I guess I'm still having a hard time understanding why you would declare cat and dog as Animal and not Cat and Dog ... since Cat IS-A Animal, you could still add it to the List<Animal>, and its speak() method would still be called from a.speak(), right? Seems the only thing that Animal is going to do is force me to cast it later if I need to access Cat-specific behavior ... or is that the idea - generic until you need specific?

Thanks again! I appreciate your patience
Tina Smith
Ranch Hand

Joined: Jul 21, 2011
Posts: 177
    
    6

That is the idea, generic until you need specific. If you know you will need specific, declare it as a Cat in the first place. But if you will not need specific, declare it as an Animal and use it as an Animal.
Tyrel Sackett
Greenhorn

Joined: Oct 23, 2013
Posts: 4

Thanks again!
timo corn
Ranch Hand

Joined: Oct 26, 2013
Posts: 68

Maybe it is good to know that with a class, you can use the method content of the superclass.



This is not possible with Interfaces, but with (inherited) classes.

Coming back to your conversation, so the idea is if I only need the generic method speak in my app, I use
Animal c= new Cat();

But if I need a detailed method of the subclass(e.g. miau()), I use
Cat c= new Cat();

If I need both, well I have to code only the Cat= new Cat Version but then I cannot do a loop over all animals.


hth
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Reference Type vs. Object Type