Java generics static type inference - java

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);
}
...

Related

How to make a reference to a concrete subtype in an abstract method definition

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.

How to find the concrete class of a method parameter

I have the following class structure:
public interface Incoming<P extends Processor> {
void doSomething(P p);
}
public interface Processor<I extends Incoming> {
void process(I i);
}
public class MyIncoming implements Incoming<MyProcessor>
{
public void doSomething(MyProcessor p) { .. }
}
public class MyProcessor implements Processor<MyIncoming> {
public void process(MyIncoming i) { .. }
}
Now in another class I pass an Instance of MyIncoming that is supposed to initialize the type passed for the Processor it has defined in doSomething()?
Please help.
The first problem I see with your code is that you are using the raw types Incoming and Processor.
public interface Incoming<P extends Processor> {
void doSomething(P p); ^^
} that is a raw type!
One way to get rid of those raw types is to make both Incoming and Processor have two type parameters, but it's very complicated.
public interface Incoming<I extends Incoming<I, P>, P extends Processor<I, P>> {
void doSomething(P p);
}
public interface Processor<I extends Incoming<I, P>, P extends Processor<I, P>> {
void process(I i);
}
Now to your actual question. You've said that for each concrete implementation of Incoming you have a specific instance of Processor, and for a variable t of type Incoming, you want to be able to find out that instance x and call x.process(t);. I'm sure that this can be done with reflection, but I can't see the point. You can just make getProcessor a method of Incoming.
public interface Incoming<I extends Incoming<I, P>, P extends Processor<I, P>> {
void doSomething(P p);
P getProcessor();
}
Now you can write concrete implementations.
public class MyIncoming implements Incoming<MyIncoming, MyProcessor>
{
private static final MyProcessor PROCESSOR = new MyProcessor();
#Override
public void doSomething(MyProcessor p) { }
#Override
public MyProcessor getProcessor() { return PROCESSOR; }
}
public class MyProcessor implements Processor<MyIncoming, MyProcessor> {
#Override
public void process(MyIncoming i) { }
}
Now, if you have a generic class
class A<I extends Incoming<I, P>, P extends Processor<I, P>>
and, within A, you have a variable i of type I, you can do
i.getProcessor().process(i);
This works, but personally I think circular dependencies of the form TypeA<B extends TypeB> / TypeB<A extends TypeA> are unnecessarily convoluted, and the generics here actually work against you. It may preserve your sanity if you just make Incoming and Processor non-generic interfaces and use casting where necessary.

Using Factory Method to Create Generics

I have an abstract class (Candy) with a generic collection (Flavors). Candy has a factory method to produce concrete instances of itself. It also has methods to get an instance of the generic flavor appropriate to the concrete candy and to add the flavor to its collection.
I know the getter is working, because if I cast the flavor from the CandyStore, the methods unique to the concrete flavor work fine. But the very last line, the addFlavor(flavor), errs (Eclipse) on me. The error is: "The method addFlavor(capture#5-of ? extends IFlavor) in the type ICandy is not applicable for the arguments (IFlavor)." Can anyone explain what is going on?
Interface:
public interface ICandy <Flavor extends IFlavor> {
public Flavor getFlavorForCandy();
public void addFlavor(Flavor flavor);
}
Abstract Class:
public abstract class AbstractCandy<Flavor extends IFlavor> implements ICandy<Flavor> {
public static ICandy<? extends IFlavor> buildCandy(String flavor){
if(flavor.equals("Jolly Rancher")
return new JolRanchCandy();
}
public Flavor getFlavorForCandy() {
return (Flavor) new CandyFlavor();
}
public void addFlavor(Flavor flavor) {
... //implemented
}
}
Concrete Class:
public class JolRanchCandy extends AbstractCandy<JolRanchFlavor> {
... //implemented
}
Used By:
public class CandyStore {
private ICandy<? extends IFlavor> candy;
private IFlavor flavor;
public void createCandy() {
candy = AbstractCandy.buildCandy("Jolly Rancher");
flavor = candy.getFlavorForCandy(); //returns a JolRanchFlavor
flavor.setName("Apple"); //etc for creating flavor
candy.addFlavor(flavor); //no luck
}
}
Edit: For clarity, JolRanchFlavor extends CandyFlavor implements IJolRanchFlavor and CandyFlavor implements IFlavor.
Try this...
public <T extends IFlavor> void createCandy() {
ICandy<T> candy= (ICandy<T>) AbstractCandy.buildCandy("Jolly Rancher");
T flavor= candy.getFlavorForCandy();
flavor.setName("Apple");
candy.addFlavor(flavor);
}
The problem is the declaration of private ICandy<? extends IFlavor> candy. Since the type of the candy is unknown and therefore ? the compiler doesn't know exactly what kind of IFlavor addFlavor should take. You just need to define a generic holder for the IFlavor type so that it is preserved.

need trick with object creator

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.

Return a nested class type in Java

I have a base class that has an abstract getType() method. I want subclasses to be able to implement this method and provide the actual class to use.
In code, something like the following:
public abstract class A {
public static interface Tile;
protected abstract Class<Tile> getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
#Override
protected abstract Class<A.Tile> getTileClass() {
MyTile t = new MyTile(); // WORKS
return MyTile; // ERROR HERE
}
}
The problem here is that I get "MyTile cannot be resolved" in the line marked. So I'm trying to return this instead:
return new MyTile().getClass()
but now Eclipse tells me:
Type mismatch: cannot convert from
Class<capture#1-of ? extends B.MyTile>
to Class<A.Tile>
which I'm not even sure if there's maybe a bug in Eclipse here top (capture#1?).
Next, I'm giving up on interfaces and trying to use an abstract base Tile class. With some help from Eclipse, I end up with the following code that seems to compile:
public abstract class A {
public static abstract class Tile;
protected abstract Class<? extends Tile> getTileClass();
}
public class B extends A {
public static class MyTile exends A.Tile { }
#Override
protected abstract Class<? extends A.Tile> getTileClass() {
return new MyTile().getClass(); // WORKS
return MyTile; // "Cannot be resolved"
}
}
So I basically seem to have three questions:
1) Is it possible to get this to work with A.Tile being an interface?
2) When using a base class, is Class<? extends X> really the correct way to go?
3) And how can I return my nested B.MyTile class reference from inside the method? Having to do new MyTile().getClass() can't be right, can it?
Generics and covariant type overriding do not work very well together. You have to explicitly declare getTileClass() as returning a class that can be a subclass of A.Tile.
You also can access the class object of MyTile without instanciating it, with MyTile.class.
Try this instead:
public abstract class A {
public static interface Tile;
protected abstract Class<? extends Tile> getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
#Override
protected Class<MyTile> getTileClass() {
return MyTile.class;
}
}
Even better would be to make A generic. You still have to use extends in the class type definition, but you can be a bit more specific:
public abstract class A<T extends A.Tile> {
public static interface Tile;
protected abstract Class<? extends T> getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
#Override
protected Class<MyTile> getTileClass() {
return MyTile.class;
}
}
public abstract class A {
public static interface Tile {};
// I return something that is-a Tile
protected abstract Tile getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
#Override
protected abstract Tile getTileClass() {
return new MyTile();
}
}
No need for generics, you just want to say that you return a Tile or Tile subclass.
Incidentally, a public static interface in a class is a "code smell"; either make it protected, so only subclasses of A can implement Tile, or put it in its own top-level interface. Putting in a but allowing anyone to implement it sends a mixed message.

Categories