• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Why declare an object and instantiate it as instance of inherited type?

 
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm unclear about the utility (as well as the true meaning) of declaring an object of one type but then instantiating it as an instance of an inherited type.

For example, let's say I have a Fruit class and two inherited classes Apple and Orange, each of which extends Fruit:

class Fruit(){...whatever...}
class Apple extends Fruit (){...whatever...}
class Orange extends Fruit (){...whatever...}

Now, I understand I can declare an object this way:

Fruit x = new Apple();
Fruit y = new Orange();

But not:

Apple a = new Fruit();
Orange b = new Fruit();

...because Fruit() well might not have all of the properties of either Apple or Orange (am I right?)

But why would you do:

Fruit x = new Apple();

...when you might as well do:

Apple x = new Apple();

???

What utility is there in the former case? What might x have when declared one way as opposed to the other? What are the situations where it provides an advantage?

And in general, why would we even need the Object type on the left side of the statement, anyway? Why not simply:

x = new Apple();

I think this points at a subtlety of a fundamental property of object instantiation that I don't grasp fully. Many thanks in advance for the help!

~~Tom
 
Saloon Keeper
Posts: 15524
364
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
https://coderanch.com/t/510989/java/java/reference-type#2310726

As for why a variable is declared in the first place, is to ensure type safety. If you don't declare your variables before you use them, how can the compiler check whether you're performing legal operations on them? Languages that have this property are called 'strongly typed'. Take a look at PHP, for instance, which is not strongly typed. You can use a variable to hold any value at all, regardless of the type of this value. This makes it easy to use, but it also makes it very easy for bugs to sneak into your code.
 
Tom Brodhead
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks...I actually understand why variables need to be declared; that's not the issue. There just seems to be a redundancy in the syntax when you have to say:

Apple x = new Apple();

...when it would seem more intuitive to do:

Apple() x;

...yes? Why have to state it twice? Ah, that's where this instantiation of an object as an child type seems to come in. Or at least that's what this notation supports. And that's where I'm still a bit confused.

If I code:

Fruit x = new Apple();

...is x a Fruit object now, or an Apple object?
 
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Tom : did you go through the link given by Stephan ?

<edit>
also please use code tag while posting your code, so that it can be easy to read.
</edit>
 
Seetharaman Venkatasamy
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
and Welcome to JavaRanch Tom
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tom Brodhead wrote:...because Fruit() well might not have all of the properties of either Apple or Orange (am I right?)


Yes. Inheritance implies an "is a" relationship from the subclass to the superclass: an instance of the subclass is an instance of the superclass. For example, an Apple is a Fruit. But that relationship obviously doesn't hold the other way around; a Fruit is not always an Apple.

Tom Brodhead wrote:
But why would you do:

Fruit x = new Apple();


Because often the rest of the program should not care if x is specifically an Apple; it just needs to know that x is a Fruit. Stephan's post already explains that (click the link). Let's look at another example.

Note that we're here declaring names as a List<String>, not as an ArrayList<String>. The rest of the program only needs to know that names is a list of strings - it does not need to know what specific implementation of interface List is used. That is good, because you might want to switch to another implementation. Suppose that you'd find out that a LinkedList would be more efficient in this case than an ArrayList. Then you'd only have to change one line of code:

In the rest of the program, nothing would need to change, because names is still a List<String>. Had you declared names to be an ArrayList<String> directly, then other parts of the program might have been calling methods that are specific to ArrayList (and that do not exist in the List interface) and it would have been more work to change it.

One of the principles of object oriented design is to decouple parts of the program as much as possible, because too much coupling makes your program a hard to maintain interconnected mess - spaghetti code. One of the ways to minimize coupling is to let other parts of the program know only what they need to know, and not more. In the example above, the rest of the program only needs to know that names is a List<String>; it doesn't need to know what particular list implementation is used.
 
Stephan van Hulst
Saloon Keeper
Posts: 15524
364
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tom Brodhead wrote:There just seems to be a redundancy in the syntax [...]


There is no redundancy. The declaration of the variable will tell the compiler what the type of the reference will be. Calling the constructor will tell the virtual machine what the runtime type is of the object referenced.

Apple x = new Apple() would only be redundant if Apples could only be referenced by variables of type Apple. This is not true. Apples can also be referenced by variables of type Fruit.
 
lowercase baba
Posts: 13089
67
Chrome Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
you also may have a collection of objects...something called fruitSaladIngredients. it contains Apples, Oranges, Grapes, Strawberries, etc.

you may want to iterate through the list, and wash() and slice() each ingredient. It's much easier to have a simple loop with one fruit reference that can in turn point to each object, than have a complicated if-else...


vs

Note that if someone decides to add a new fruit to your salad (i.e. honey dew melons), the first chunk of code DOES NOT NEED TO BE TOUCHED. In the second example, you have to add a whole new 'else-if' block. And if you later decide you need to also peel the fruit, in the first case you only need to add it in one spot. the second example you have to add it in each and every block - and it's possible there could be dozens if not hundreds of types...
 
Master Rancher
Posts: 4830
74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Tom Brodhead wrote:There just seems to be a redundancy in the syntax [...]


There is no redundancy.


Mmmm, I think a lot of us still see redundancy here. Yes, the type of the reference and the type of the instance are different things - and as Fred shows, sometimes it's extremely useful for them to be different. The thing is, many times, it isn't - and we just type the same thing twice:

This is considered normal in Java, but that doesn't mean it isn't redundant. The Scala language for example allows users to omit many of these redundant declarations, while still retaining all the type information we're used to having in Java. The Scala version of this would be:

And the compiler just figures out that the type of reference foo is SomeReallyLongClassName. If you need the type to be something different, it's possible to specify that. But often you don't have to, and this works out just fine. With less verbosity.

Anyway, to Tom's question: yes, it's often redundant. But it's the way we do things in Java. And it's important to understand that the type of the reference and the type of the instance are not necessarily the same, and that sometimes this is an extremely useful distinction.
 
Tom Brodhead
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the very detailed help!

If I understand correctly, in:

Fruit x = new Apple();

...the LEFT side of the equation defines the REFERENCE type, while the RIGHT side of the equation defines the OBJECT type. (Yes?) This means that any object can have a reference type that is distinct from its object type.

So, the x.getClass() method would return the object type here: Apple. But is there a standard method that would return the reference type of an object?

 
Stephan van Hulst
Saloon Keeper
Posts: 15524
364
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No, an object doesn't have a reference type. An object knows nothing about the variable that references it. At runtime, the type of the reference is unimportant, it gets thrown away. It is only useful to the compiler.

Yes, x.getClass() will return the type of the object at runtime.
 
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Something that may or may not help those struggling with the rules and regulations here that I think is good to keep in mind: the reference type, and also casting, never change the type of the object at runtime. You can declare reference to be Fruit, and/or you can cast it to Fruit, but it is always an Apple, and nothing in Java will change the object to be a different type.

Just for my 2 cents, I don't see the two mentions of the classname as redundant, I see it as consistent. When you instantiate an object, 'new' and a constructor reference is the way you do it. You do that whether or not it is on the same line as the declaration.

Humans see the same class name twice close together in an operation that is common in Java. Humans would be able to understand many things that would eliminate having to put them close together like that. But it would be a new syntax that the compiler, etc., would have to understand, and would increase the "clutter" of rules one would have to learn about Java.

I understand why people do see it as redundant, I'm just saying I'm glad this is the way it is.

rc
 
Tom Brodhead
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I wrote the following to help me grasp the distinctions we're discussing. I'd be most interested in corrections to the comments I've made in the code, because my commentary will be my reference for understanding this in the future (it reveals what I do and don't understand about the code I've written.) Many thanks!

 
Jesper de Jong
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Looks like you understand the concepts!

Tom Brodhead wrote:...the LEFT side of the equation defines the REFERENCE type, while the RIGHT side of the equation defines the OBJECT type. (Yes?) This means that any object can have a reference type that is distinct from its object type.


The first sentence is more or less correct. Variables in Java are references to objects. Variables can have a type that is not the same as the type of the object they are referring to - for example, you can have a variable that has the type Fruit, while it's really referring to an object that has the type Apple.

The second sentence is incorrect. The object itself doesn't know anything about the variable that refers to it. In fact, multiple variables may refer to the same object:

The Apple object does not somehow keep track of the variables that refer to it.

It is not the object that has a "reference type" and an "object type" - an object has a type, and any variables that refer to it each have a type.
 
reply
    Bookmark Topic Watch Topic
  • New Topic