I'm new to the F-Bounded interface concept.
I have a F-Bounded interface, A. I want to use it in the interface B. I only want to use generics on A, but if I don't use generics, B will throw warnings.
I'm looking for the best practice in this case. It would be nice to show also the implementation of B with the best solution.
public interface A<T extends A<T>>{
T getSomething();
void setSomething(T);
}
Here is the one i would like to use, but it obviously throws warnings.
public interface B{
A getA();
void setA();
}
This one works just fine, as long as they are few interfaces. As soon as I add more interfaces which i.e. using B, things get totally messy.
public interface B<T extends A<T>>{
T getA();
void setA(T);
}
Also, should I use the implementation of A in the interface B? This would eliminate the recurring generics, but it doesn't feel right.
Simply use an unbounded wildcard.
public interface B{
A<?> getA();
void setA(A<?> a);
}
Related
This is an existing interface:
public interface MyInterface<T, U> {
public T foo(U u);
}
I want to implement this interface under the assumption that T and U are the same type. I thought maybe I could leave the type parameters in as they are, and then as long as I only ever instantiate this particular implementation with two of the same type, that it might work:
public class MyOuterClass<A> {
public class MyClass<T, U> implements MyInterface<T, U> {
#Override
public T foo(U u) {
return u; //error here
}
//even though in the only instantiation of MyClass, T and U are the same
private MyClass<A, A> myInstance = new MyClass<A, A>();
}
But, perhaps unsurprisingly, this doesn't work, as types T and U are incompatible.
So then I thought maybe I could change MyClass to specify that its types would always be the same, by changing it to something like MyClass<A, A> implements MyInterface<A, A> or similar, but I get errors saying that T is already defined.
Is there a way to implement MyClass so that its two types will be the same?
(I'm more of a C++ guy than Java, so sorry if I'm missing something fundamental about Java's generic's here.)
Your myclass needs to look like this:
public class MyClass<T> implements MyInterface<T, T> {
#Override
public T foo(T in) {
return in;
}
}
Let's review what your suggested class definition does:
public class MyClass<T, U> implements MyInterface<T, U>
In this code, T and U do two things each:
in the first occurance they define a type variable of your MyClass class
in the second occurance they specify the concrete type of the MyInterface class
Since inside the body of your class T and U are unbounded type variables (i.e. nothing is known about the actual types), they are assumed to be incompatible.
By having only a single type variable in your MyClass you make your assumption explicit: there's only a single type, and I'm using it for both types of the interface.
Last but not least: remember that the compilation of a type is complete once the source is fully handled. In other words: contrary to what C++ does, "instantiation" of a generic type ("template type" or similar in C++; Sorry for my rusty terminology) does not handle. MyClass<Foo> and MyClass<Bar> are the same type, as far as the JVM is concerned (only the compiler actually distinguishes them).
Define a single type parameter for MyClass:
class MyOuterClass<A> {
public class MyClass<T> implements MyInterface<T, T> {
public T foo(T u) {
return u;
}
}
// Need only one 'A' here.
private MyClass<A> myInstance = new MyClass<A>();
}
When you say
public class MyClass<T> implements MyInterface<T, T> {
... you are defining one generic variable for MyClass and you are saying that it fulfills both the roles T and U in MyInterface.
The problem:
base interface:
IBase
descendants:
InterfaceA extends IBase<Interface1>
InterfaceB extends IBase<Interface2>
When I try:
InterfaceC extends InterfaceA, InterfaceB
I receive compile error:
The interface IBase cannot be implemented more than once with different arguments
Does exist workaround?
Thanks.
This is not possible and it cannot be in Java, at least.
Think of the following scenario:
interface Base<K> {
K get();
}
interface A extends Base<String> {
String get();
}
interface B extends Base<Integer> {
Integer get();
}
interface AB extends A, B {
??
}
When you go try to implement AB, if it were possible, what type would the get() method return. In Java, two methods in a class cannot have the same name/args but different return types.... hence, this is forbidden.
If you actually need some functionality similar to what you would get should Java allow this, I would suggest the following:
abstract class C {
A a;
B b;
String aGet() {
return a.get();
}
Integer bGet() {
return b.get();
}
}
Or, to keep generics:
abstract class C<K, T> {
Base<K> a;
Base<T> b;
K getA() {
return a.get();
}
T getB() {
return b.get();
}
}
Generics are basically compile time check only, so InterfaceA and InterfaceB are the same.
A general workaround for what you are suggesting is hard to come up with, you would probably have to specify your exact situation more. But do you really need THAT class to implement the two, why not two different classes? Maybe nested classes, or even anonymous inner class?
I am calling a specific class using only its interface. The problem is, the class itself implements Comparable, but because I am referring to the class via a different interface, the compiler does not know it implements Comparable. I'm sure there is an easy solution to this... but I just can't think of it right now.
Will everything that implements the interface also implement Comparable<T>? If so, I suggest you just make the interface extend Comparable<T>.
Otherwise, you could just cast to Comparable<T> if you happen to know that in this case it will work. Of course, that loses some compile-time type safety, but that's the nature of the beast.
This seems odd to me... if you have main like the following, you can make it work with the Parent interface and Child classes below... but there is an oddity in that you could try to compare a ChildA to a ChildB which probably doesn't make sense to do.
Maybe if you gave us a hint at what the classes/interface are doing we could give a better answer.
public class Main
{
public static void main(final String[] argv)
{
Parent x;
Parent y;
x = new ChildA();
y = new ChildA();
x.compareTo(y);
}
}
abstract interface Parent
extends Comparable<Parent>
{
}
class ChildA
implements Parent
{
public int compareTo(Parent o)
{
throw new UnsupportedOperationException("Not supported yet.");
}
}
class ChildB
implements Parent
{
public int compareTo(Parent o)
{
throw new UnsupportedOperationException("Not supported yet.");
}
}
I'd suggest you to use Comapartor instead. You can use sort(list, Comparator). Your comparator implementation will cast class to Comparable and use its compare method. So the compiler will be satisfied and you will reuse the existing implementation of compare method.
You can do some freaky generics. Let's say the main interface is Lickable (which defines a method lick()), and you want a method that will process objects which are Lickable and Comparable. You write:
public <LickableAndComparable extends Lickable & Comparable<LickableAndComparable>> void lickGreater(LickableAndComparable a, LickableAndComparable b) {
if (a.compareTo(b) > 0) a.lick();
else b.lick();
}
You can then call that with objects of any type which is both Lickable and Comparable. Note that it only works if both arguments share a type which is both Lickable and Comparable to itself. If you only have one class in mind, then this should be fine. You may run into migraine-inducing compiler errors if your usage of the method gets complicated.
Comparable interfaces are tricky. In general, if you mark an interface as Comparable to itself, any correct implementation may only use methods from this interface to perform the comparison. Otherwise this relation can't be made anti-symmetric - a necessary condition to have a consistent ordering.
So think twice before marking an interface as comparable.
There is however a workaround in your case, if you are sure you are not mixing different implementations of your interface:
interface Foo {
}
interface Bar extends Foo, Comparable<Bar> {
}
class FooComparator<T extends Foo & Comparable<T>> implements Comparator<T> {
#Override
public int compare(T arg0, T arg1) {
return arg0.compareTo(arg1);
}
}
I want to have a function defined in a superclass that returns an instance of the subclass that is used to invoke the function. That is, say I have class A with a function plugh. Then I create subclasses B and C that extend A. I want B.plugh to return a B and C.plugh to return a C. Yes, they could return an A, but then the caller would have to either cast it to the right subtype, which is a pain when used a lot, or declare the receiving variable to be of the supertype, which loses type safety.
So I was trying to do this with generics, writing something like this:
class A<T extends A>
{
private T foo;
public T getFoo()
{
return foo;
}
}
class B extends A<B>
{
public void calcFoo()
{
foo=... whatever ...
}
}
class C extends A<C>
{
public void calcFoo()
{
foo=... whatever ...
}
}
This appears to work but it looks pretty ugly.
For one thing, I get warnings on class A<T extends A>. The compiler says that A is generic and I should specify the type. I guess it wants me to say class A<T extends A<x>. But what would I put in for x? I think I could get stuck in an infinite loop here.
It seems weird to write class B extends A<B>, but this causes no complaints, so maybe that's just fine.
Is this the right way to do it? Is there a better way?
class A<T extends A<T>> {
Or, I prefer:
class A<THIS extends A<THIS>> {
Like java.lang.Enum. It uglifies client code that just wants A, but has to write A<?>.
Note this does not in any way break LSP, and is GOOD OO.
Or you could just use covariant return types.
Doing this is, from a strictly OO perspective, a Very Bad Thing™. It violates the Liskov Substitution Principle for one - if B & C are both A, then B.getFoo() and C.getFoo() should return the same thing - which in this case they won't. If the caller needs to know what it's getting when it calls the method, there's a good chance your inheritance hierarchy is wrong.
I have an interface for a variety of classes, all of which should implement Iterator, so I have something like
public interface A extends Iterable<A> { ...otherMethods()... }
For the concrete classes, however, this means I must use
public class B implements A { public Iterator<A> iterator() {...} }
when I'd prefer (or at least, think I'd prefer) to use public Iterator<B> iterator() {...} so that concrete use of the class could have the explicit type (in case I wanted methods that weren't in the interface to be available, or some such. Maybe that should never come up? Or it's poor design if it does?
The flipside is that using the Iterator interface
public interface A extends Iterator<A> { ...otherMethods()... }
the concrete classes compile just fine with
public class B implements A { public B next() {...} }
What gives?
Carl was right, my first answer didn't compile but this seems to. Not sure if it's what you want exactly.
public interface A<T extends A> extends Iterable<T> {
}
public class B implements A<B> {
#Override
public Iterator<B> iterator() {
return null;
}
The concrete class compiles fine because B extends A, and since Java 5 a return type on a subclass can be a subclass of the return type on the superclass.
As for the generic, I have hit the same wall, and you have two options that I know of.
One is to paramaterize A:
public interface A<T extends A> extends Iterable<T>
then:
public class B implements A<B>
However, that has a disadvantage that you will need to give a parameter of A, instead of having it fixed, even if you want A:
private class NoOneSees implements A<A>
As to the question of if you actually want Iterator<B>, in the case of an Iterable, most likely that is preferable, and considering that these are interfaces, the need to redeclare the parameter is probably reasonable. It gets a little more complicated if you start inheriting concrete classes, and for things that have meaning other than an Iterable, where you may want covariance. For example:
public interface Blah<T> {
void blah(T param);
}
public class Super implements Blah<Super> {
public void blah(Super param) {}
}
public class Sub extends Super {
public void blah(Super param) {}
//Here you have to go with Super because Super is not paramaterized
//to allow a Sub here and still be overriding the method.
}
Similarly for covariance, you can't declare a variable of type Iterator<A> and then assign an Iterator<B> in it, even if B extends A.
The other option is live with the fact that further implementation/subclasses will still reference A.
The other answers have the right gist - but you'll get the right mechanics by declaring the generic type as
A<T extends A<T>>
This forces a class to return an iterator that is of its own type or lower - so you would be able to declare
class B implements A<B>
but not
class B implements A<A>
which I suspect is closer to what you want (i.e. implementations must return iterators over themselves, rather than simply over As).
Note that your experiences with Iterator vs Iterable stem from the lack of covariance of generic types; an instance of B is an A, but an Iterator<B> is not an Iterator<A>.
I guess this is what you want:
public interface A<T extends A<?>> extends Iterable<T>
public class B implements A<B> {
public Iterator<B> iterator() {...}
}
Your design decisions are your own, but I can't think of any reason for EVERY class in a design to implement Iterable. There must be some kind of thing that is contained in a collection but isn't actually a collection itself. I would take a long hard look at the fundamental design. Maybe some iterables will want to return iterators of things that are not related to themselves.