1

I've found a number of questions about the java limitation of not being able to implement the same interface twice with different type paramters. (e.g., you can't be Iterable<String> and Iterable<Integer>), but I haven't found any discussion of the following case.

I can say

    public class A implements Iterable<Integer> {    
        public Iterator<Integer> iterator() {
            throw new UnsupportedOperationException();
        }
    }

and I can say

    public class A<T> {
        T getFoo() { 
            throw new UnsupportedOperationException();
        }
        void setFoo(T foo) { 
            throw new UnsupportedOperationException();
        }
    }

But it's not clear to me why the following isn't allowed. [See correction below.] It seems like the first case already "drops" the type Integer from the generic specification of A (I didn't have to say A<Integer> in case #1.) So why can't we give A a new type T like this?

    public class A<T> implements Iterable<Integer> {
        T getFoo() { 
            throw new UnsupportedOperationException();
        }
        void setFoo(T foo) { 
            throw new UnsupportedOperationException();
        }
        public Iterator<Integer> iterator() {
            throw new UnsupportedOperationException();
        }

    }

By the way, if I change the first case to

    public class A<Integer> implements Iterable<Integer> {

I get a "hiding" warning, that the Integer (on the left I presume) is hiding the other type Integer.

Actually, that's not quite right! Changing it to

    public class A<String> implements Iterable<Integer> {

says that String is hiding String, not hiding Integer. I'm not even sure what that means. A<String> is allowed with Iterable<Integer> while A<T> is not — that's the crux of my question.


Edit:

I found the problem with my example. For the example, I changed to Iterable<Integer> from our own interface LinkableVertex<OurLinkClass>, thinking it didn't make a difference. OurLinkClass already implemented LinkableEdge<A>. The actual error in Eclipse is:

Bound mismatch: The type OurLinkClass is not a valid substitute for the
bounded parameter <E extends LinkableEdge<? extends LinkableVertex<E>>> of 
the type LinkableVertex<E>

(In case it's relevant, this is a recursive pair of interfaces: LinkableVertex<E extends LinkableEdge<? extends LinkableVertex<E>>> and LinkableEdge<V extends LinkableVertex<? extends LinkableEdge<V>>>)

That said, while I haven't got it all cleared up, and I'm not sure why the extra type is required instead of just a raw type warning, the problem may be as simple as changing OurLinkClass to implement LinkableVertex<A<?>>

Sorry about that!

Joshua Goldberg
  • 5,059
  • 2
  • 34
  • 39

1 Answers1

2

The hiding means that the name used for your generic may be hiding a class: java.lang.String.

There's a huge difference between using generics for class definition and using it for variable (local, parameter, field, etc) definition.

It's not the same to define this:

public class A<String> {
             //^----^----- name of your generic used in the class
    public String getFoo() {
    }
}

Than declaring this:

A<String> a; //here A will work with generics but using java.lang.String class

Also, your class can implement an interface that use generics but that doesn't mean your class must use generics as well. Here's an example:

class MyClass<T> implements Iterable<T> {
    //this means MyClass will use a generic of name T and implements Iterable
    //to support the same generic T used in the class
}

class AnotherClass implements Iterable<String> {
    //this means that AnotherClass doesn't support generics
    //and implements Iterable for java.lang.String only.
}
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332