Extending a generic implementer class - java

I have a DAO object that I'd normally extend with the entity class name like so:
public class DAO<T> {
private final Class<T> clazz;
public DAO(Class<T> clazz {
this.clazz = clazz;
}
}
public class EntityDAO extends DAO<Entity> {
public EntityDAO() {
super(Entity.class);
}
}
However, I have some abstract entities that I would like to create an abstract DAO that gets implemented into a concrete class later on:
public class DAO<T> {
private final Class<T> clazz;
public DAO(Class<T> clazz {
this.clazz = clazz;
}
}
public abstract class AbstractEntityDAO extends DAO<T extends AbstractEntity> {
public AbstractEntityDAO () {
super(AbstractEntity.class);
}
}
public abstract class EntityDAO extends AbstractEntityDAO <Entity> {
public EntityDAO() {
super(Entity.class);
}
}
But this doesn't work as the AbstractEntityDAO complains about an unexpected bound and it cannot resolve T. Is it possible to do this? And if so, how is it written?
This is using Java 1.7

Put the generic type definition on AbstractEntityDAO:
public abstract class AbstractEntityDAO<T extends AbstractEntity> extends DAO<T> {
...
}
With your current code AbstractEntityDAO <Entity> should make the compiler complain about AbstractEntityDAO not having generic paremeters.
Besides that your AbstractEntityDAO() constructor needs to accept a Class parameter as well. However, you don't need to pass the class as a parameter at all if you always use instances of classes with concrete types. Using reflection a class can determine the type of T if there is a concrete definition as in EntityDAO. The built-in reflection utilities provide no easy way to do this but fortunately you only need a little additional code to provide one, have a look here: http://www.artima.com/weblogs/viewpost.jsp?thread=208860
That's basically what we're doing as well. Here's a rough rundown of our approach:
abstract class BaseDAO<T> {
Class<?> entityClass;
BaseDAO() {
//this is based on the link I posted above but basically uses the actual concrete class
//(subclass determined by getClass() ) to extract the generic types and
//since we only have one we get the first one from the returned list
entityClass = ReflectionHelper.getTypes(getClass(), BaseDAO.class).get(0);
}
public T getEntity(Object id) {
...
}
}
abstract class TranslatableDAO<T extends TranslatableEntity> extends BaseDAO<T> {
...
}
//Users are not translatable
class UserDAO extends BaseDAO<User> {
...
}
//Products are translatable, i.e. Product extends TranslatableEntity
class ProductDAO extends TranslatableDAO<Product> {
...
}

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.

Accessing Class implementing generic abstract class

when i try to instantiate an object, from a class that extends a generic abstract class. It won't let me since the generic abstract class does not have a suitable constructor.
public abstract class AbstractClass<T> {
private final Class<T> entityClass;
public AbstractClass(Class<T> entityClass) {
this.entityClass = entityClass;
}
}
this is the generic abstract class I am talking about.
public class Imp extends AbstractClass {
public Imp(Class entityClass) {
super(entityClass);
}
}
If i want to ever access the Imp class, then I would try to instantiate it through a normal constructor. But i get following error when trying:
public class Imp extends AbstractClass {
public Imp(){
}
public Imp(Class entityClass) {
super(entityClass);
}
}
constructor AbstractClass in class AbstractClass cannot be applied to given types required: Class
So if i understand correctly, by extending a generic abstract class you cannot instantiate the class anywhere ever?
If not being able to access the Imp class from other classes, how should I ever use the class?
you need to extend it like that:
public class Imp<T> extends AbstractClass<T> {
public Imp() {
super(null); // you need to call an existing constructor from superclass (nothing specific about generic classes)
}
public Imp(Class<T> entityClass) {
super(entityClass);
}
}
Never use a generic class without generic parameters.
Just guessing, but maybe you actually want something like this:
public class IntegerImpl extends AbstractClass<Integer> {
public IntegerImpl () {
super(Integer.class);
}
}
If you want to use a no-arg constructor to initialize Imp class, then AbstractClass should have this (no-arg) constructor as well, but 'entityClass' property cannot be final anymore in this case.
This could lead to possible null pointer exceptions if you use 'entityClass' without not null checks.

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.

Generic type parameter which implements generic interace

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

Using a generic type of a subclass within it's abstract superclass?

Within my code a have the following abstract superclass
public abstract class AbstractClass<Type extends A> {...}
and some child classes like
public class ChildClassA extends AbstractClass<GenericTypeA> {...}
public class ChildClassB extends AbstractClass<GenericTypeB> {...}
I'm searching for an elegant way how I can use the generic type of the child classes (GenericTypeA, GenericTypeB, ...) inside the abstract class in a generic way.
To solve this problem I currently defined the method
protected abstract Class<Type> getGenericTypeClass();
in my abstract class and implemented the method
#Override
protected Class<GenericType> getGenericTypeClass() {
return GenericType.class;
}
in every child class.
Is it possible to get the generic type of the child classes in my abstract class without implementing this helper method?
BR,
Markus
I think its possible. I saw this was being used in the DAO patterns along with generics. e.g.
Consider classes:
public class A {}
public class B extends A {}
And your generic class:
import java.lang.reflect.ParameterizedType;
public abstract class Test<T extends A> {
private Class<T> theType;
public Test() {
theType = (Class<T>) (
(ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
// this method will always return the type that extends class "A"
public Class<T> getTheType() {
return theType;
}
public void printType() {
Class<T> clazz = getTheType();
System.out.println(clazz);
}
}
You can have a class Test1 that extends Test with class B (it extends A)
public class Test1 extends Test<B> {
public static void main(String[] args) {
Test1 t = new Test1();
Class<B> clazz = t.getTheType();
System.out.println(clazz); // will print 'class B'
System.out.println(printType()); // will print 'class B'
}
}
I'm not sure I fully understand your question - <Type> is the generic type of the subclass, even when it's being expressed in the abstract class. For example, if your abstract superclass defines a method:
public void augment(Type entity) {
...
}
and you instantiate a ChildClassA, you'll only be able to call augment with an instance of GenericTypeA.
Now if you want a class literal, then you'll need to provide the method as you indicated. But if you just want the generic parameter, you don't need to do anything special.

Categories