简体   繁体   中英

Generics- am I missing something or what is the point?

I have the following code:

public class AClass<X extends AnInterface> implements AnotherInterface {

    public AClass(X x){
    }

}

Why would I use X as the constructor parameter type, when I could just replace this with AnInterface ?? Surely they mean the same thing, anything which is a subtype of AnInterface ?

I am trying to keep all my parameter types as generic and only mention Interface names in the generic parametric declarations eg "X extends AnInterface" but running into problems because it is saying the value I pass in, which is of type AnInterface, is not equal to type X.

EDITED:

public void<X extends AnInterface> myMethod(){


    AnInterface b = new ADiffClass();
    AnotherInterface a = new AClass(b);
}

public class ADiffClass<X extends AnInterface> implements AnInterface {

    public ADiffClass(){
    }

}

This is where I am having problems, I get a compile error saying that the type of b is AnInterface and the type required in the constructor of AClass is X.

Suppose you have this situation:

public class AClass<X extends AnInterface>{

    public AClass(X x){
        ...
    }

    public X getIt() {
        ...
    }

}

The one who is creating the object will have an interface accordingly to it, in this situation it would be useful.

For instance:

// supposing DefaultAnInstance is an implementation of AnInstance interface
DefaultAnInterface obj = new DefaultAnInterface();
AClass<DefaultAnInterface> instance = new AClass<DefaultAnInterface>(obj);
...
// for the user getIt will return an objecct of type DefaultAnInterface
DefaultAnInterface obj = instance.getIt(); // there is no need to cast it to DefaultAnInterface

If you declare a variable like this:

private AClass<Foo> a;

the following will be valid:

 a = new AClass<Foo>(new Foo());

but the following wwon't:

 a = new AClass<Foo>(new Bar());

(assuming Foo and Bar are two implementations of AnInterface ).

That's the point of generics in that case: restrict the type to a specific type that implements (or extends) AnInterface.

Why are you trying to extend an interface? Do you mean to implement it? I think the problem is that you are using a class where you should be using an interface. If you want to be able to pass in something of multiple classes, that is precisely what an interface is for.

Given your AClass, you may want it to be less general than your average generic - it can't handle any type, like a generic such as LinkedList can, but you want it to be able to handle a lot of classes.

For example, let's say you've got a class SelfSortingList, which is generic. All of its objects need to be comparable for it to be sortable. But you don't want to allow Widgets and Levers, which both implement Comparable, to be in the same list; that wouldn't make sense, and their particular implementations of Comparable probably reflect that.

So what you do is you say, "I want my SelfSortingList to be able to hold Objects of the same type, but they must be comparable." That's why you have both a type parameter (X) and a limitation on what X can be (extends Comparable) in the class header SelfSortingList.

There's no reason you couldn't. However, this would probably break the rest of your generic class:

public class AClass<X extends AnInterface> {
    private X anInterface;
    public AClass(AnInterface anInterface) {
       // Not legal.  You'd have to narrow cast to X
       this.anInterface = anInterface;
    }
}

So, you could always change the declaration of "anInterface" to AnInterface instead of X. However, generics are not giving you anything, since you're not referring to X anymore

public class AClass<X extends AnInterface> {
    private AnInterface anInterface;
    public AClass(AnInterface anInterface) {
       // Not legal.  You'd have to narrow cast to X
       this.anInterface = anInterface;
    }
}

Where's the use of X? You'd be inserting a generic parameter which isn't used.

Then there's the also the constructor typesafety issues some mentioned in another answer.

And these two constructors DO NOT MEAN THE SAME THING:

public AClass(AnInterface anInterface) { ... }
public AClass(X anInterface) { ... }

The first means you can have ANY class that is assignment compatible with AnInterface (ie. implements or extends it). The second means that you can have any class which is assignment compatible with the supplied generic parameter, which may be MORE SPECIFIC than just AnInterface. Someone used this example above:

public class Int1 implements AnInterface { ... }
public class Int2 implements AnInterface { ... }
public class Int3 extends Int1 { ... }

So if you have:

AClass<Int1>  --> it could accept either Int1 or Int3, but not Int2 in the constructor
AClass<Int2>  --> it could accept only Int2 in the constructor

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM