Generics name clash
Asked Answered
E

2

6

Consider:

public interface Foo<T> {
    public static class X{}
    public void foobar(T t); 
}

public class Bar<X> {
    Foo<X> foo = new Foo<X>() {
        public void foobar(X t) {}
    };
}

I found no way to express that I mean the X from Bar<X> and not Foo.X in the foobar(X t) implementation. Is there no other way than renaming the generic parameter X in Bar or the static inner class?

Elba answered 21/1, 2012 at 16:51 Comment(3)
That doesn't look right... can you nest a public class (even static) inside an interface?Trivandrum
Yes, if you rename either the static inner class or the generic parameter of Bar, it compiles.Elba
@Daniel ... Yes you can. It looks funny, but its completely valid.Bolognese
C
9

I don't think there is a way to disambiguate to the type parameter, and I think that that was a reasonable design decision to make.

  1. The conventions are clear that type parameters should be one character long if possible, and the flipside to this is that other classes shouldn't have one-character names.
  2. If you had the ability to disambiguate, then you would have the ability to rename the type parameter X in Bar<X>. In other words, if you had the ability to say foobar(TypeParameter.X t) you would have the ability to simply use something other than X for the type parameter on Bar. Renaming X is the way you avoid name clashes.

Don't forget that type parameter names don't leak out to other classes in more than trivial ways. You are never forced to use a certain type parameter name, ever. So it makes sense that the language designers wouldn't have thought this is worth adding complexity to the language for.

Carrera answered 21/1, 2012 at 17:44 Comment(1)
I tend to agree with your second point, but not with the first one: Java's lack of syntax for pretty basic things like Closures or Tuples forces you to use wrappers, and if you work on code heavily relying on these wrappers, you quickly start to use names like F or P instead of Function or Product (see e.g. functionaljava.org ).Elba
E
0

the compiler wont even bother to determine if you meant Foo.X, it will consider the TypeParameter X, regardless, unless you typed something like:

public class Bar<X> {
    Foo<X> foo = new Foo<X>() {
        public void foobar(Foo.X t) {}
    };
}
Euboea answered 21/1, 2012 at 18:9 Comment(1)
No, that's not true. Inside the anonymous class we are in the scope of class Foo, so Foo.X shadows the type parameter X of the outer class.Elba

© 2022 - 2024 — McMap. All rights reserved.