This discussion is archived
7 Replies Latest reply: May 6, 2012 10:39 AM by 935199 RSS

"Elevating" generics in subclasses

935199 Newbie
Currently Being Moderated
Hi!

I'm trying to figure out a nice way to "elevate" generics in parent classes to something more specific in subclasses. Let me explain.

I have a class callled LazyTreeNode that has a field of type List<LazyTreeNode>. I have public methods such as public LazyTreeNode getChild(int index). Now, if I make a subclass, say ImageTreeNode, I want the public methods that accept and return LazyTreeNodes to instead enforce accepting ImageTreeNodes or returning more specifically ImageTreeNodes.

How can I do this? I can of course override all the methods and call super.methodName() but I'm thinking there must be a cleaner solution, because then you have to cast upwards. The whole point of generics (in my opinion) is to never have to cast upwards (explicitly), which I consider ugly. Any ideas?

Thanks!
  • 1. Re: "Elevating" generics in subclasses
    EJP Guru
    Currently Being Moderated
    See java.util.Comparable and its uses. It does exactly that.
  • 2. Re: "Elevating" generics in subclasses
    935199 Newbie
    Currently Being Moderated
    I'm sorry, could you explain further? What I've used Comparable<> before is to allow objects to be sorted (java.lang one, I'm assuming). An example would be helpful: allow me to provide some sample code:
    public class Foo {
        protected List<Foo> myFoos;
    
        public Foo get(int index) {
            return myFoos.get(index);
        }
    
        public void add(Foo foo) {
            myFoos.add(foo);
        }
    }
    
    public class Bar extends Foo { // class should have list of Bars instead!
        // ...
    }
    
    public class Main {
        public static void main(String[] args) {
            Bar bar = new Bar();
            bar.add(new Bar()); // OK! 
            bar.add(new Foo()); // Should return a compile-time error!
            bar = bar.get(3); // Will throw compile-time casting error - should accept!
        }
    }
    What would I do to achieve the desired behaviour in the comments, without having to cast upwards?
  • 3. Re: "Elevating" generics in subclasses
    EJP Guru
    Currently Being Moderated
    Look at how it's declared. Comparable<T extends Comparable<T>>. That gives it T as the actual Comparable type for use within the class body. So the compareTo() method can take a T, not just a Comparable, and if there was a method that returned anything it could return T instead of Comparable. This is exactly what you want.
  • 4. Re: "Elevating" generics in subclasses
    935199 Newbie
    Currently Being Moderated
    Brilliant. I think I tried a similar solution in a previous, unrelated project, but the compiler complained about a wildcard in the parametrization declaration, so I must have believed declaring them like that was impossible. Marking as helpful, will check the syntax in my own project and report - thanks a million!
  • 5. Re: "Elevating" generics in subclasses
    935199 Newbie
    Currently Being Moderated
    I stumbled across a problem. Here's what my structure was, loosely:
    public class Foo<T extends Foo<T>> {
        protected List<T> myFoos;
     
        public T get(int index) { // fine!
            return myFoos.get(index);
        }
     
        public void add(T foo) { // fine!
            myFoos.add(foo);
        }
    
        public void addMyselfToFoos() {
            myFoos.add(this); // compile error, because "this" is not considered a T, but it should be...?
        }
    }
     
    public class Bar extends Foo {
        // ...
    }
    Any help is greatly appreciated.
  • 6. Re: "Elevating" generics in subclasses
    EJP Guru
    Currently Being Moderated
    You'll have to cast. At least the problem is inside the class.
  • 7. Re: "Elevating" generics in subclasses
    935199 Newbie
    Currently Being Moderated
    Too bad - I guess my dreams of a cast-free Java have to be put to rest. At least for the moment. Thanks for your help!

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points