I need to defined a Generic type as a subclass implementing an interface, like this (DOES NOT COMPILE):
public class Foo<T extends SomeClass implements SomeInterface> {
...
}
Is it possible to do something like this?
Jon Skeet, where are you when we need you ;)
That's the syntax:
public class Foo<T extends SomeClass & SomeInterface> {
}
These are called Intersection Types. They don't differentiate between classes and interfaces. Intersection types are also briefly mentioned in the Java tutorial on Bounded Type Parameters.
Related
I want to have a Class object, but I want to force whatever class it represents to extend class A and implement interface B.
I can do:
Class<? extends ClassA>
Or:
Class<? extends InterfaceB>
but I can't do both. Is there a way to do this?
Actually, you can do what you want. If you want to provide multiple interfaces or a class plus interfaces, you have to have your wildcard look something like this:
<T extends ClassA & InterfaceB>
See the Generics Tutorial at sun.com, specifically the Bounded Type Parameters section, at the bottom of the page. You can actually list more than one interface if you wish, using & InterfaceName for each one that you need.
This can get arbitrarily complicated. To demonstrate, see the JavaDoc declaration of Collections#max, which (wrapped onto two lines) is:
public static <T extends Object & Comparable<? super T>> T
max(Collection<? extends T> coll)
why so complicated? As said in the Java Generics FAQ: To preserve binary compatibility.
It looks like this doesn't work for variable declaration, but it does work when putting a generic boundary on a class. Thus, to do what you want, you may have to jump through a few hoops. But you can do it. You can do something like this, putting a generic boundary on your class and then:
class classB { }
interface interfaceC { }
public class MyClass<T extends classB & interfaceC> {
Class<T> variable;
}
to get variable that has the restriction that you want. For more information and examples, check out page 3 of Generics in Java 5.0. Note, in <T extends B & C>, the class name must come first, and interfaces follow. And of course you can only list a single class.
You can't do it with "anonymous" type parameters (ie, wildcards that use ?), but you can do it with "named" type parameters. Simply declare the type parameter at method or class level.
import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
T t;
}
I've seen examples of how to declare a generic class whose type parameter is constrained, e.g. it must extend Comparable. I also know how to define an interface for a generic class whose type is similarly constrained. However, when I do the latter, I'm unable to figure out the syntax for the class signature. So, to cut a long story short, if the interface is
public interface iMyClass<T extends Comparable<T>>
what should be the syntax for the signature for the implementing class
public class MyClass.......
Thanks in advance,
D
Do you intend MyClass to be generic as well? If so,
public class MyClass<? extends Comparable<T>> implements iMyClass<T> {
Otherwise, keep things simple and
public class MyClass implements iMyClass<String> {
Replace String with your Comparable.
A constrained type argument is supplied in exactly the same way as a non-constrained one, for instance:
public class MyClass implements iMyClass<String> {
This question is a follow up from Java Generics Wildcarding With Multiple Classes.
I'm writing an interface like this:
public interface SomeInterface {
public Class<? extends SomeClass implements OtherInterface> getClassForObject(Object object);
}
I know that this is wrong syntax, as is Class<? extends SomeClass & OtherInterface>, and it seems all options.
I can't have the interface do what was suggested in the answer to the question linked above (public interface SomeInterface<T extends SomeClass & OtherInterface>) because implementations of this interface might want to return different things for different inputs.
I also can't create an abstract class that extends SomeClass and implements OtherInterface and have everything extend from that because there are many existing implementations of SomeClass that clients may want to extend from.
Is there any way to force implementations of this interface to return a type that fits both constraints? Besides throwing a runtime exception somewhere else in the code?
You cannot impose multiple restrictions on a wildcard. You can declare a generic type parameter on the method instead of the interface itself, and you can impose multiple restrictions on it. Try:
public interface SomeInterface {
public <T extends SomeClass & OtherInterface> Class<T>
getClassForObject(Object object);
}
It might be a noob question but I am learning java and I came across an interface which had its definition like :
public interface MyClass <T extends Comparable<T>>
Can someone please explain what does it mean? I mean what kind of interface is created.
It means that the generic type argument must implement the Comparable interface.
When specifying <T extends Comparable<T>> you can use e.g. Collections.sort in this interface on type T. Without extends you can not guarantee that T is comparable.
Numbers and String are e.g. comparable and implement the Comparable interface.
The interface takes a type T which is Comparable with other T.
The interface is much the same only its generic type is constrained.
It means that T must implement Comparable over the same object.
for example
public interface MyClass <T extends Comparable<T>>
en then you can use as follow
public class MyImpl implements MyClass<String>
It is valid because String implements Comparable. But the following sentence is not valid because MyNewImpl is not implementing Comparable.
public class MyNewImpl {}
public class MyImplTwo implements MyClass<MyNewImpl>
Regards
Ignacio
I want to create a class that takes two parameters. One should be typed simply as T. The other should be typed as something that extends both T and SomeInterface<T>. When I attempt this with
public class SomeClass<T, S extends SomeInterface<T> & T>
then Java complains with
"The type T is not an interface; it cannot be specified as a bounded parameter"
and if instead I attempt to create an interface for S with
public interface TandSomeInterface<T> extends SomeInterface<T>, T
then Java complains with
"Cannot refer to the type parameter T as a supertype"
Is there any way to do this in Java? I think you can do it in C++...?
You can't create an interface that extends the type parameter T since there's no contract that would guarantee T to be an interface. And of course interface extending a class is not allowed.
this works if you extend an interface as well:
public class SomeClass<T extends I, S extends SomeInterface<T> & I>
but maybe it's not exactly what you want ...