11

The code:

interface Property<T>
{
    T get();
}

class BoolProperty implements Property<Boolean>
{
    @Override
    public Boolean get()
    {
        return false;
    }
}
class StringProperty implements Property<String>
{
    @Override
    public String get()
    {
        return "hello";
    }
}
class OtherStringProperty implements Property<String>
{
    @Override
    public String get()
    {
        return "bye";
    }
    public String getSpecialValue()
    {
        return "you are special";
    }
}

is used by my class:

class Result<P extends Property<X>, X>
{
    P p;
    List<X> list;
}

As you see it has two type parameters P and X. Despite of that the X can always be deduced from P but the language requires me to supply both:

Result<BooleanProperty, Boolean> res = new Result<BooleanProperty, Boolean>();

Is there any trick to get rid of the X type parameter? I want just use

Result<BooleanProperty> res = new Result<BooleanProperty>();

Also, I don't want lose type information and use it as:

Result<OtherStringProperty> res = new Result<OtherStringProperty>();
String spec = res.p.getSpecialValue();
String prop = res.list.get(0);
kan
  • 28,279
  • 7
  • 71
  • 101
  • 1
    Is there type-specific behaviour in the Property subclasses? If not, then you can just refer to the properties via the Property interface instead of a non-generic subclass – Gnat Dec 07 '11 at 14:28
  • @Gnat Yes, there is. I've updated the question to mention it. – kan Dec 07 '11 at 16:24
  • @derek has linked another answered question about the same type that explains why you won't be able to do that. – Caesar Ralf Dec 07 '11 at 16:52

4 Answers4

4

I would change Result class to be something like

class Result<X> {
    Property<X> property;
    List<X> list;
}

I don't think the compiler can infer X from Property, as your Result class is waiting two definitions for the two generics.

Caesar Ralf
  • 2,203
  • 1
  • 18
  • 36
  • Cannot use it, as the `Result` class should know exact type of Property. – kan Dec 07 '11 at 14:43
  • If I may, why? I imagine it's because you only have the reference one of Preferences Implementation. As you want it to be generic, I would change it to have a reference to the interface Preference instead of it. If the problem is related to methods that receives collections of Preference as parameters, you just need to use generic wildcard Collection extends Preference> (PS: sorry for my poor english) – Caesar Ralf Dec 07 '11 at 15:28
1

You can't infer the type, but you can add an extra level of indirection:

class BoolProperty implements Property<Boolean>
{
    @Override
    public Boolean get()
    {
        return false;
    }
}

class Sub<X, P extends Property<X>> {
    P p;
    List<X> list;
}

class Result<X> extends Sub<X, Property<X>> {
}

Result<Boolean> res = new Result<Boolean>();
List<Boolean> list = res.list;
Boolean b = res.p.get();
List<String> res2 = res.list; // compilation error
Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
0

Have you tried using the wildcard generic?

class Result<? extends Property<X>>
{
    // stuff
}
Platinum Azure
  • 45,269
  • 12
  • 110
  • 134
  • Yes, but then I cannot use it further in the class, i.e. `List` will be un-typed. – kan Dec 07 '11 at 14:22
0

There is a similar question whose answer you might find interesting: https://stackoverflow.com/a/4452268/247763

Essentially, there's no real way to get around including the extra generic type, because the compiler can't know what type you're using without it. I'm guessing this defeats the purpose of your approach, but you could try extending Result while specifying the types - something like this:

class BoolResult extends Result<BoolProperty, Boolean> {
    // Do stuff
}
Community
  • 1
  • 1
derekerdmann
  • 17,696
  • 11
  • 76
  • 110
  • ColinD in the linked answer says "for good reason", but I don't understand the reason. Does anybody know? – kan Dec 07 '11 at 20:28
  • @kan - It's so that the compiler knows the type is actually generic, and isn't some other concrete type (like a Double), as in the example. – derekerdmann Dec 07 '11 at 21:04
  • It's just a syntax problem. It could be a special way to mark such type parameters. Why is it not just a missing feature of the compiler? – kan Dec 07 '11 at 22:57
  • @kan - for that, you'll have to ask someone at Oracle. I wish I knew. – derekerdmann Dec 08 '11 at 00:37