• 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
  • Tim Cooke
  • Ron McLeod
  • paul wheaton
  • Jeanne Boyarsky
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
  • Himai Minh
Bartenders:

Sibling assignment

 
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

This is from a mock exam.
Answer:
Illegal both at compile and runtime, you cannot assign an object to a sibling reference, even with casting.
I thought I have seen plenty of examples on here regarding GC where this assignment is OK. Can anyone explain why they;re saying this is illegal?
 
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes,

"DerivedOne" is a "Parent" plus something
"DerivedTwo" is a "Parent" plus something
"DerivedOne" is not a "DerivedTwo"
"DerivedTwo" is not a "DerivedOne"
for example

When DerivedTwo is created it allocates memory for a and c but no b. If this assigment were legal....
What prints this code?

[ January 29, 2002: Message edited by: Carlos R Ram�rez ]
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What prints this code?
I would say d1 now holds d2 object therefore would print contents of d2. I still think this assignment should be ok, since all we're doing is reassigning the ref var d1.
 
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Paul,
The compiler checks for assignment compatibility of the declared types. The VM does a double check at runtime on the actual types.
DerivedOne and DerivedTwo are not assignment compatible because they are siblings. Although they have a common parent, they may extend the parent in very different ways, i.e. they do not have a direct "is a" relationship. You can't say "a DerivedOne is a DerivedTwo or vice versa".
What would be legal at compile time is this code:

The above code would pass compilation. However, at runtime a ClassCastException will be generated at line 3.
Try substituting the following names to make it more meaningful and you'll see the logic in having Java behave this way:
Parent --> Mammal
DerivedOne --> Whale
DerivedTwo --> Mouse
 
Author & Gold Digger
Posts: 7617
6
IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The assignment would be ok if the compile-time type of d1 and d2 was Parent, like this:

You have to understand that DerivedOne and DerivedTwo have NOTHING in common regardless of the fact that htey both inherit from Parent... They are sibling, just sibling...
Moreover, think of Parent as Fruit and DerivedOne as Apple and DerivedTwo as Orange. Now you must admit that an Apple and an Orange have nothing in common. They can both be referenced by a reference of type Fruit but an object of type Apple cannot be referenced by a reference of type Orange and vice-versa...
HIH
 
Ranch Hand
Posts: 3271
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
When dealing with inheritance, I've found that it is most important to remember one simple rule:
You can use a child anywhere a parent is expected.
Note, this says you can use a child anywhere a parent is expected. It doesn't say that you can use a sibling or cousin or whatever. When you have an inheritance relationship, you have an "is a" relationship. Take the following example:

I hope this makes sense to you. Here's another way to explain it.
A child class is a specialization of a parent class. Let's assume we have the class Animal. An animal class might have a few basic traits, like a name, number of feet, a backbone, etc. Here's a simple Animal class:

Now, let's think about a couple things that might extend Animal, such as bird and dog. What might those classes look like. Obviously, they'll have everything that an Animal would have, but they'll each have a little bit more. Here are some class definitions for Bird and Dog:

As you can see, a bird "is a" type of animal as a dog "is a" type of animal. Therefore, the following code snippet is legal:

Since a variable of type Animal can reference anything that "is an" animal, we can assign an Animal object, a Bird object, or a Dog object to it. Now, what happens if we try to assign a Dog object to a Bird variable:

Since b is a Bird variable, we should be able to call it's layEggs method. Yet, we've tried to assign a Dog object to b. Can a dog lay eggs? Not one that I've ever seen! Since a dog "is not" a bird, we can't assign a dog to a bird variable (and vice versa).
Also, what about assigning parents to siblings. Look at this code:

Once again, since d is a Dog reference, we should be able to tell anything that is assigned to it to catch a frisbee. But, can any animal catch a frisbee? Can a frog? or a tadpole? An animal "is not" a dog, rather a dog "is a" animal. Therefore, you can't assign a parent to a child variable, either.
I know this reply has gotten horribly long, but this is an essential topic and you'll have to understand this very well if you want to go far with Java. Please let me know if you're still having problems.
Corey
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks guys for the great explanations. I was just under the impression that d1 was just a reference variable then after reassignment ie d1 = d2 the d1 would just loose its reference to the original object, where it could then be GC'd.
Heres an example I had previously although both reference vars point to the same object.

I realize this wont compile but when a=b the object to which "a" was originally reffering to is now GC'd. This is what Chubb gave me, great example ha?
 
Valentin Crettaz
Author & Gold Digger
Posts: 7617
6
IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Excellent explanation Corey
You explained with Animals, I explained with Fruits, let's hope it clear things up
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But I think I got it now, after viewing the three posts combined. Thanks guys
 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi corey,
nice explanation..very clear with the concept now.. thanx
Praveena
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One more thing:


The compiler checks for assignment compatibility of the declared types. The VM does a double check at runtime on the actual types.
DerivedOne and DerivedTwo are not assignment compatible because they are siblings. Although they have a common parent, they may extend the parent in very different ways, i.e. they do not have a direct "is a" relationship. You can't say "a DerivedOne is a DerivedTwo or vice versa".


I realize this is an illegal assignment, Im just looking for a quick answer because Im seeing something different in a multiple choice mock.
They say that it will compile, but throw a ClassCastException at Runtime, but I'm under the impression that it wont even compile based upon the above "quoted" information.
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
to clear up he says
Parent p = new Parent();
DerivedOne d1 = new DerivedOne();
DerivedTwo d2 = new DerivedTwo();
d2 = d1;

Legal at compile time, but may fail at runtime.
but this one:
Parent p = new Parent();
DerivedOne d1 = new DerivedOne();
DerivedTwo d2 = new DerivedTwo();
d1 = (DerivedOne)d2;

Illegal both at compile and runtime.
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey guys,
So I guess I'm wondering if those two assessments are correct. Again I realize that sibling to sibling assignment is invalid, but I'm still trying to determine exactly what types of errors occur in the two cases above?
Thanks!
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Paul Salerno:
to clear up he says
Parent p = new Parent();
DerivedOne d1 = new DerivedOne();
DerivedTwo d2 = new DerivedTwo();
d2 = d1;

Legal at compile time, but may fail at runtime.
but this one:
Parent p = new Parent();
DerivedOne d1 = new DerivedOne();
DerivedTwo d2 = new DerivedTwo();
d1 = (DerivedOne)d2;

Illegal both at compile and runtime.



No, Paul. Neither of these is legal at compile time because you can't say that a DerivedOne 'is a' DerivedTwo or vice versa.
As we've tried to explain previously,
An Orange 'is a' Fruit (vice versa may be true)
An Apple 'is a' Fruit (vice versa may be true)
A Whale 'is a' Mammal (vice versa may be true)
A Mouse 'is a' Mammal (vice versa may be true)
BUT
An Apple is NOT an Orange (not ever, nor vice versa)
A Whale is NOT a Mouse (not ever, nor vice versa)
By the same token,
A DerivedOne is NOT a DerivedTwo (not ever, nor vice versa)
You can't trick the compiler into thinking otherwise because it is aware of the class hierarchy.
You can, however, say:
1: Parent p = new DerivedOne();
2: DerivedTwo d2 = (DerivedTwo) p;
Because in line 1, the statement "Parent IS A DerivedOne, or vice versa" applies.
Line 2 is legal because in effect, you are telling the compiler "This reference p, which you only know to be a Parent references an object that is really a DerivedTwo."
The compiler, God bless its trusting soul , takes your word for it and goes about its business. As long as one class IS A descendant of the other (doesn't matter which one, hence, the "or vice versa"), the compiler will be happy.
The Runtime is not as gullible. It goes back and double checks your assurance. If it finds out you weren't being truthful, it will tell you in no uncertain terms that you have made an Invalid Class Cast. Line 2 will placate the compiler, but not the Runtime (because it knows... <"twilight zone" music> ).
[ January 31, 2002: Message edited by: Junilu Lacar ]
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Paul Salerno:
I realize this is an illegal assignment, Im just looking for a quick answer because Im seeing something different in a multiple choice mock.


Oops, sorry for that long-winded explaination just now. I was under the impression that you hadn't gotten it.
The short of it is:
Compiler checks that this is true:
- Declared type (DT) of Right Hand Side (RHS) instanceof DT of Left Hand Side (LHS) (or if reverse is true, require a valid cast as an assurance)
Runtime checks that this is true:
- Actual type of RHS instanceof DT of LHS (violations to this will be dealt with a ClassCastException )
As somebody explained before, it is important that you are clear on the difference between Declared Type and Actual Type. In
Parent p = new DerivedOne();
the Actual Type is DerivedOne while the Declared Type is Parent.
[ January 31, 2002: Message edited by: Junilu Lacar ]
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your quick reply, this is really helping me nail down my study notes!

thirdly I'm assuming that since the compiler checks the declared types that the following will compile and run:
 
Paul Salerno
Ranch Hand
Posts: 172
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Im sorry, just forget this thread I have it figured out. Thanks
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic