• 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

inner class generics issue

 
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm trying to extend LinkedList by overriding the listIterator() method to return a customized iterator, which is created by an inner class extending ListIterator.



Ideally, I wanted to do this by accessing the enclosing class's get(), etc. methods. But:



But what happens is I get told:



This means I instead have to pass the list instance into the iterator constructor and make it a private variable, so I can go:



etc. Seems a little stupid. Does this mean it is impossible to access generically typed fields, methods, etc from an inner class matching the type of the enclosing class?
 
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So you need to access the instance of the outer class? See https://coderanch.com/t/573871/java/java/Inner-classes-pointer-parent#2612252
 
Marcus Kelvin
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Martin Vajsar wrote:So you need to access the instance of the outer class? See ....



I can access the instance of the outer class. That is not the problem. In plainer language: the inner class implements ListIterator<T>, therefore its next() method must return an item of type T. I want to get this by calling get(), which implicitly belongs to the outer instance (a LinkedList derived object) and returns an item of type T. But the compiler says the T of the inner instance cannot be considered the same as the T of the outer instance, therefore I cannot meaningfully make use of the access to the outer instance -- instead, I have to pass it in and work with that reference:



Using list.get() works, because the compiler is fine with the fact that it returns type T. But if I just use get() (method of the instance of the outer class) the compiler sees it as a type mismatch, so I cannot make meaningful use of that access. The "inner class" might as well be a completely separate class. Make sense?
 
Martin Vashko
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh, I'm sorry, I was not paying enough attention.

By declaring your iterator class as CircularIterator<E>, you're introducing a new type parameter E, which, though it has the same name, has no relation to the type parameter E of the outer class. So the solution is to simply not declare the parameter in the CircularIterator class definition; that way the E (which is valid throughout the source code, including any inner classes) will be the E of the outer class.

You might want to try to take a look at the LinkedList source, to see how it is handled there.
 
Marcus Kelvin
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Martin Vajsar wrote:So the solution is to simply not declare the parameter in the CircularIterator class definition; that way the E (which is valid throughout the source code, including any inner classes) will be the E of the outer class.



That works, I just get a bunch of "unchecked conversion" warnings I guess I need to suppress. The constructor is private, so that shouldn't matter.

Thanks.
 
Martin Vashko
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Marcus Kelvin wrote:That works, I just get a bunch of "unchecked conversion" warnings I guess I need to suppress. The constructor is private, so that shouldn't matter.

Thanks.


You're welcome

Still, I'd expect that to compile clean. Could you post more of the code, just enough for the warnings to be seen?
 
Marcus Kelvin
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Martin Vajsar wrote:
Still, I'd expect that to compile clean. Could you post more of the code, just enough for the warnings to be seen?



Sure. I haven't tested this yet as I only finished it a minute ago, but it compiles and I think the general idea is clear:

 
Bartender
Posts: 4568
9
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I haven't tried it, but can you declare CircularIterator implements ListIterator<T>? It feels like that ought to be allowed, because the CircularIterator always sits within a CircularList<T>. And if it works you've got a fully generic solution and you won't get the warnings.
 
Martin Vashko
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The line 27 of your code should look like this instead:

This is the way to "force" the outer T parameter over the CircularIterator class. You'll have to change a few method declarations inside the inner class to take/return T instead of Object, but then it should compile without warnings.

It should not take much time to understand what's happening here. Once you do, you'll understand generics a tad better again.
 
Marcus Kelvin
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
"CircularIterator implements ListIterator<T>" did the trick, thanks gang.

Martin Vajsar wrote:You'll have to change a few method declarations inside the inner class to take/return T instead of Object,



Actually, the issue there was that add(T) clashed with the outer class's add() method, whereas add(Object) did not but still satisfied the ListIterator interface requirement. Interestingly, this last change seems to have mitigated that problem as well -- now add(T) is fine. Not quite sure why that would make a difference but
reply
    Bookmark Topic Watch Topic
  • New Topic