This is my code:
public interface InterfaceA<J>{
// …
}
public interface InterfaceB extends InterfaceA<String> {
// …
}
public interface InterfaceC extends InterfaceA<Long>{
// …
}
public class Creator<J, I extends InterfaceA<J>> {}
public abstract class Base<J, J1> implements InterfaceA<J> {
protected Creator<J, J1> creator;
protected Base() {
creator=ObjectCreator.createCreator();
}
}
public class Extension1 extends Base<Integer> implements InterfaceB {
// …
}
public class Extension2 extends Base<Double> implements InterfaceC {
// …
}
I want Extension1 to have Creator<Integer, InterfaceB> and Extension2 to have Creator<Double, interfaceC>. See the pattern? Creator<T1, T2> where T1 is the type of immediate parent and T2 is the interface implemented by said class. Is there any way to do this? can anybody tell the code of ObjectCreator.createCreator()?
Right now my code looks like this:
public class ObjectCreator {
public static <J, I extends InterfaceA<J>> Creator<J, I> createCreator() {
return new Creator();
}
}
I got errors all over my code. I'm really confused. What am I missing here?
There's a whole bunch of stuff you missed, a compiling version would look something like this:
package scratch;
interface InterfaceA<J> {
// …
}
interface InterfaceB extends InterfaceA<String> {
// …
}
interface InterfaceC extends InterfaceA<Long> {
// …
}
class Creator<J, I extends InterfaceA<J>> {
}
abstract class Base<J, I extends InterfaceA<J>> {
protected Creator<J, I> creator;
protected Base(Class<J> jClass, Class<I> iClass) {
creator = ObjectCreator.createCreator(jClass, iClass);
}
}
class Extension1 extends Base<String, InterfaceB> implements InterfaceB {
protected Extension1() {
super(String.class, InterfaceB.class);
}
}
class Extension2 extends Base<Long, InterfaceC> implements InterfaceC {
protected Extension2() {
super(Long.class, InterfaceC.class);
}
}
class ObjectCreator {
public static <J, I extends InterfaceA<J>> Creator<J, I>
createCreator(Class<J> jClass, Class<I> iClass) {
return new Creator();
}
}
In no particular order of importance:
When you have a class with a signature like createCreator() has, you need to pass Class objects as type tokens to it. The Java compiler can't infer the types based on the type of the variable you're assigning the return value to. Besides, you want them there anyway because of type erasure, otherwise you couldn't specialise the Creator based on the given types.
If you have Base<J, I> with two type parameters, extending classes should use both of those type parameters.
Your extension class signatures were odd. You can't have class Extension1 extends Base<Integer, InterfaceA<String>>, because you can't have a Creator<Integer, InterfaceA<String>>. Using explicit type tokens in createCreator() would have forced you to propagate this constraint everywhere it needs to be and made the error less mysterious. You can't really make Base independent of the constraint between the J and I type parameters.
Related
Suppose I have the following definition:
public abstract class SomeAbstractClass {
public abstract List<SomeAbstractClass> getNextElements() ;
}
If I build a concrete class that extends SomeAbstractClass named for instance SomeConcreteClass I would like getNextElements to have the following signature:
public List<SomeConcreteClass> getNextElements()
Instead of:
public List<SomeAbstractClass> getNextElements()
In other words, I would want my abstract definition to have a type depending on the current concrete type. Can it be done ? If so, how ?
Just use Java generics:
public abstract class SomeAbstractClass<T extends SomeAbstractClass> {
public abstract List<T> getNextElements() ;
}
public class SomeConcreteClass extends SomeAbstractClass<SomeConcreteClass> {
#Override
public List<SomeConcreteClass> getNextElements() {
return new ArrayList<>();
}
}
Another possibility would be to use only generic methods as follows:
public abstract class SomeAbstractClass {
public abstract <T extends SomeAbstractClass> List<T> getNextElements();
}
public class SomeConcreteClass extends SomeAbstractClass {
#Override
public List<SomeConcreteClass> getNextElements() {
return new ArrayList<>();
}
}
The downside of this is that you now have an unchecked conversion at List<SomeConcreteClass> getNextElements() which may potentially trigger ClassCastException at runtime.
Please, consider my code:
interface AInterface {}
interface BInterface extends AInterface {}
class AClass implements AInterface { }
class BClass extends AClass implements BInterface {}
class Descriptor<S extends AClass, T extends AInterface> {
private Class<S> classClass;
private Class<T> interfaceClass;
public Descriptor(Class<S> classClass, Class<T> interfaceClass) {
this.classClass = classClass;
this.interfaceClass = interfaceClass;
}
}
class Foo {
public void test() {
Descriptor<AClass, BInterface> descriptor =
new Descriptor<>(AClass.class, BInterface.class);//LINE X
}
}
So, I have two interfaces and two classes that implement them. And I have a descriptor to which I must add two classes - the class of the interface and class of the implementation. The question is how to add relation restrict between them. I mean, that at LINE X I must get compilation error, because AClass doesn't implement BInterface. How to do it?
I do not think this is possible. Enforcing multiple type bounds is possible when all of them but the first one (optionally) are interfaces, but I'm unaware of any trick allowing to do it for multiple classes. Here's how it works for interfaces:
public class Bar {}
public class Baz extends Bar {}
public class Foo1<T extends Bar & Serializable> {} // compiles
public class Foo2<T extends Serializable & Bar> {} // doesn't compile
public class Foo2<T extends Bar & Baz> {} // doesn't compile
public class Foo3<T extends Serializable & Closeable> {} // compiles
public class Foo4<T extends Serializable & Closeable & Runnable> {} // compiles
What's your real use case? Perhaps there's a way to approach the problem differently.
I'd like to improve my code especially my way to use Generic classes.
In my project I have about 30 classes like folowing :
GenericEntity<T extends Serializable>{
protected T id;
public T getId(){ return id;};
...
}
public class A extends GenericEntity<Integer>{
...
}
public interface IService<T extends GenericEntity, T extends Serializable>{
...
}
public class AService extends IService<A,Integer>{
...
}
I would like to specify the class of my entity Id only one time instead of one in GenericEntity and one in Service like that.
public class A extends GenericEntity<getIdType()>{
public final static Class getIdType(){
return Integer.class;
}
}
public class AService extends IService<A,A.getIdType()>{
...
}
I'm aware it doesn't work like that but I'm hoping there is a way to do it.
Thanks for your help.
Instead of:
class GenericEntity<T extends Serializable>{
protected T id;
public T getId(){ return id;};
}
// THESE ARE UNNECESSARY as far as I can tell
class A extends GenericEntity<Integer>{ }
class B extends GenericEntity<Long>{ }
// where U matches the generic type of GenericEntity<?>
interface IService<T extends GenericEntity<?>, U extends Serializable>{ }
class AService extends IService<A, Integer>{ }
class BService extends IService<B, Long>{ }
You could do this:
class GenericEntity<T extends Serializable> {
protected T id;
public T getIdFromEntity() { return id; }
}
// 'IService' can/should only know of 'id' as some type that extends 'Serializeable'
// So if something implements 'IService' then everything knows it will have
// a method with the signature 'T getGenericEntity(Serializable id);'
interface IService<T extends GenericEntity<?>> {
public T getGenericEntity(Serializable id);
}
// 'AService' knows that 'id' will be an 'Integer'
class AService implements IService<GenericEntity<Integer>> {
Map<Serializable, GenericEntity<Integer>> entityMap = new HashMap<>();
void someMethod() {
GenericEntity<Integer> entity = this.getGenericEntity(Integer.valueOf(1));
Integer i1 = entity.getIdFromEntity();
// ... do stuff
}
// even though 'AService' knows that 'id' will be an 'Integer'
// the 'IService' interface defines this as taking a 'Serializable'
// so it must keep that method signature.
#Override public GenericEntity<Integer> getGenericEntity(Serializable id) {
return entityMap.get(id);
}
}
class BService implements IService<GenericEntity<Long>> {
#Override public GenericEntity<Long> getGenericEntity(Serializable id) { return null; }
// ... similar to AService ...
}
This would cut out all your excess class X extends GenericEntity<SOME_TYPE> classes.
You would only need the one generic GenericEntity<T extends Serializable> and the one interface IService<T extends GenericEntity<?>>. Also, since they aren't generic AService and BService know the actual type that extends Serializeable (Integer and Long), so they don't need the extra info passed to them in generics.
Since IService is generic for any T extends GenericEntity<?> it shouldn't know a concrete type for genericEntity.getId() (and you probably shouldn't want it to). Also you should avoid making it concrete because it's an Interface.
The type of id as far as IService cares is Serializable, since IService<GenericEntity<?>> implies that the wildcard ? extends Serializeable since class GenericEntity<T extends Serializeable> requires it to.
In a Java application, I'd like to use a generic type parameter which implements an interface which uses a generic parameter itself.
public interface SuperInterface<T> { ... }
public interface MyInterface extends SuperInterface<MyClass> { ... }
public class Worker<T extends SuperInterface<U>> extends SuperWorker<String, Boolean> {
}
However, the class declaration won't work like that. T should be of type MyInterface (or any other interface which implements the SuperInterface) and U should be of type MyClass (or any other class according to the interface).
You have to declare all of the type parameters at the top level. It's annoying, but that's how it is.
public class Worker<U extends MyClass, T extends SuperInterface<U>> { ...
The order of the parameters doesn't matter; you can also do Worker<T extends..., U extends...>. All that matters is that each is declared at the top level of the nested generics.
Here's a complete class:
public class MyClass {
public interface SuperInterface<T>{}
public interface MyInterface extends SuperInterface<MyClass> {}
public class Worker<U extends MyClass, T extends SuperInterface<U>> {}
public void compileTest() {
// just to make sure the declaration compiles
Worker<MyClass, MyInterface> worker = null;
}
}
I do have an abstract class with an delegation interface defined:
public abstract class MyAbstractClass extends AsyncLoader {
public interface MyAbstractClassDelegate<M> {
//The parameter in this method should be the concrete subtype of MyAbstractClass
public M performThisCall(MyAbstractClass concreteSubclassOfAbstractClass);
}
private MyAbstractClassLoaderDelegate delegate;
...
}
The Problem is, I do not want the delegate parameter to be MyAbstractClass, instead it should be the concrete subclass. Why? Because the implementation of the delegate needs the concrete subclass for further handling and I don't want to cast it...
I know I could define an Interface in each subclass, but it'll look the same in every subclass except for the parameter type
EDIT
Here is the perfect solution solving exactly what I wanted. Great thanks!
public abstract class MyAbstractClass {
public interface MyAbstractClassDelegate<M, Subtype extends MyAbstractClass> {
public M myMethod(Subtype t);
}
}
Is this possible with java 6 and if yes - how?
My solution would be:
public final class Example<T extends Example<T>> {
public interface Interface<M, Subtype extends Interface<M, Subtype>> {
public M myMethod(Subtype t);
}
}
You have no access to the generic from the outer class inside the interface (because the interface is static) so you have to declare it again.
If you use your interface you get something like this:
private static class Impl1 implements Interface<String, Impl1> {
#Override
public String myMethod(final Impl1 t) {
return null;
}
}
I don't know if it will help but here is my complete example:
public final class Example<M, T extends Example.Delegate<M, T>> {
public interface Delegate<M, Subtype extends Delegate<M, Subtype>> {
public M myMethod(Subtype t);
}
private T delegate;
private static class Impl1 implements Delegate<String, Impl1> {
#Override
public String myMethod(final Impl1 t) {
return null;
}
}
public static void main(String[] args) {
Example<String, Impl1> example = new Example<>();
example.delegate = new Impl1();
example.delegate.myMethod(example.delegate); //works but whout?
}
}
What you could do is to give your abstract class a type parameter with the concrete subclass, similar to the way Java's Enum does it.
Something along the lines of this:
public abstract class MyAbstractClass<S extends MyAbstractClass<S>> extends AsyncLoader {
public interface MyAbstractClassDelegate<M, S> {
public M performThisCall(S concreteSubclassOfAbstractClass);
}
...