• Post Reply Bookmark Topic Watch Topic
  • New Topic

casting objects with parameterized types  RSS feed

 
Will Jones
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can anyone help me understand this?



The first thing with a and b works fine. But if I stick them in a List< > then... y and x yield a type mismatch error. I can try casting x to (List<ArrayList<String>>) but it still fails with a type mismatch, cannot convert, error.

The reason I'm asking is because I have a class that implements an interface let's call it IMyClass. I want to now cast an array list of MyClass objects... ArrayList<MyClass> to a list of IMyClass objects... List<IMyClass>.
But this is failing for me just like my first example above.



How can accomplish what I'm trying to do?

Thanks.
 
Paul Clapham
Sheriff
Posts: 22834
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't. Here's the analogous example which I recall from Oracle's generics tutorial:



So you're going to have to want something else, because you can't assign List<X> to List<SuperClassOfX>. It's impossible to tell what you do want, though, because you've obfuscated your requirements with bogus class names. Perhaps you could explain?
 
Will Jones
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your help Paul.

In your Oracle generics tutorial example you explained that you can't cast a String to an Object and then expect to use it like an Integer because a String... just isn't an Object. That makes sense to me. But in my case I am talking about an interface, not a super class. An Object is a super class of a String, but an interface (such as IMyClass or List<String>) that my class (such as MyClass or ArrayList<String>) implements is not a super class, and as I demonstrated with the code snipped using "b = a;" we see that we can in fact safely cast in that situation (from an implementer of an interface to an object with the same type as that interface). But the moment I take the exact same example and make them parameters in a class with a parameterized type such as List<T> I get the casting error. That was what was confusing me. If, in my original example, I can cast "b = a;" safely then why can't I cast "y = x;" ? What is the difference? How could I remedy it?

Since you were wondering about my specific use case I'll try to be a bit more transparent and perhaps that will help show what I'm trying to do. I am using Vaadin as a UI framework and I am trying to have separation of layers in an MVP like scenario. In my presenter I wanted to receive a generic List<IMyDataField> rather than interacting with a BeanContainer<String,MyTableRow>. I was considering wrapping the Vaadin BeanContainer (used to bind data to tables) in a custom class I created called BeanContainerList that implements List. Then in my View layer I could have references to BeanContainer<String, MyTableRow> and in my Presenter layer I could have a more agnostic reference to the same thing but as a List<IMyDataField> where IMyDataField is an interface that implements a subset of methods on MyTableRow. (MyTableRow is just a simple bean class with getters and setters.) By doing this I was hoping to generalize my presenter references so that if the view were to ever change the presenter layer could essentially remain as is.

Thanks for your thoughts...
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will Jones wrote:How can accomplish what I'm trying to do?

As Paul says, you can't...and moreover, why would you want to? The definition of your 'x' variable seems kind of pointless to me, since 'y' covers all bases.

For things like collections, you generally only want interfaces on the left of an '=' (and certainly inside the angle brackets); the implementation is on the right and, for a recursive structure like a List of Lists, the only thing that you should concern yourself with is the outer implementation.

Winston
 
Paul Clapham
Sheriff
Posts: 22834
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will Jones wrote:But in my case I am talking about an interface, not a super class. An Object is a super class of a String, but an interface (such as IMyClass or List<String>) that my class (such as MyClass or ArrayList<String>) implements is not a super class...


Well, "extends" versus "implements" is an unimportant detail in the example I gave, so it makes no difference.

Here's one way of dealing with the issue:


So maybe "List<? extends IMyDataField>" would work for you.
 
Will Jones
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, I see what you mean. Yeah, that helps me. Thanks.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will Jones wrote:By doing this I was hoping to generalize my presenter references so that if the view were to ever change the presenter layer could essentially remain as is.

Very laudible; although I should warn against taking that too far (guilty myself), because you can end up with a lot of code (or complexity) for situations that actually aren't likely to arise. I'm not saying don't do it; just be careful you don't overdo it.

Generics is not a 100% solution (although it's pretty darn good if you use it right), it is merely an aid. And a compile-time aid at that.

Ask yourself this: Should your 'presenter' be worried about (or be responsible for) the type of List it's receiving, or indeed the type of IMyClass?
Chances are: probably not.

Ergo: Get to a List<List<IMyClass>> as fast as you possibly can. It's the responsibility of the classes that populate them to make sure that the contents are correct. For a structure as complex as that you can't really rely on compiler type-checking. Although structuring your load methods correctly may help.

Winston
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will Jones wrote:
In your Oracle generics tutorial example you explained that you can't cast a String to an Object and then expect to use it like an Integer because a String... just isn't an Object. That makes sense to me. But in my case I am talking about an interface, not a super class. An Object is a super class of a String, but an interface (such as IMyClass or List<String>) that my class (such as MyClass or ArrayList<String>) implements is not a super class, and as I demonstrated with the code snipped using "b = a;" we see that we can in fact safely cast in that situation (from an implementer of an interface to an object with the same type as that interface). But the moment I take the exact same example and make them parameters in a class with a parameterized type such as List<T> I get the casting error. That was what was confusing me. If, in my original example, I can cast "b = a;" safely then why can't I cast "y = x;" ? What is the difference? How could I remedy it?


Let's revisit the example.

With this...



An ArrayList IS-A List, or specifically, an ArrayList of strings IS-A List of strings. After the assignment, both the a and b reference now point to the same object -- and you can use the object with either reference in a way to not break the other reference.

With the second case...



While an ArrayList IS-A List, and an ArrayList of strings IS-A List of strings, as shown in the previous example -- A List of ArrayList of strings is NOT IS-A List of List of strings. If it was then after the assignment, both the x and y reference now point to the same object -- and you can use the object with either reference in a way to not break the other reference.

If the compiler had allowed it, then we can use the y reference to add a LinkedList of strings to the List. After all, a LinkedList of strings IS-A List of strings, and hence, can be added to a List of List of strings. Of course, since the x reference points to the same object, it is now broken -- as it is supposed to point to a List of ArrayList of strings, and that List has a LinkedList of strings as one of the elements.

Henry
 
Will Jones
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Henry... that really helped me understand the answer to my question. So actually using Paul's solution... this is what could be done...


Also, thanks for the tip Winston. I realize I could be overcomplicating things. I'll try to keep caution in mind.

Thanks everyone.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will Jones wrote:So actually using Paul's solution... this is what could be done...

Yes, but again: BEWARE. Definitions like that are usually only good for reading.

Winston
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!