generic abstract factory method
Hello generics experts,
I need some generics advise. In a simpel persistence framework I have the following case:
abstractclass BaseHandler{
public List produceSomeStuff( String condition ){
List result =new ArrayList();
//.. do stuff
result.add( make( attribs ));
//.. do more stuff
return result;
}
publicabstract Object make( attribs );
}
publicclass AHandlerextends BaseHandler{
public List<A> getSomeA( String condition ){
List<A> result;
List resObj = produceSomeStuff( condition );
// make List<A> from resObj;
return result;
}
public A make( attribs ){
returnnew A( attribs );
}
}
publicclass BHandlerextends BaseHandler{
public List<B> getSomeB( String condition ){
List<B> result;
List resObj = produceSomeStuff( condition );
// make List<B> from resObj;
return result;
}
public B make( attribs ){
returnnew B( attribs );
}
}
I would like to use generics in the BaseHandler to get the right type of list back, instead of an object list.
Problem is, that if I make the abstract make method generic, the concrete make methods have to be generic too
and I cant call new A(), new B() any more. Plus it seems I have to pass the A.class, B.class token around alot.
Any advise on this ?
I tried to use List<?> as BaseHandler.produceSomeStuff() return type, but this cant be assigned to List<A>.
Arne Stabenau
[2928 byte] By [
DoneThata] at [2007-11-27 3:59:19]

# 2
Hello, thanks for looking into this.
I agree I was a lazy typer and A and B I shouldnt have used.
class Customer {
String name;
public Customer( String name ) {
this.name = name;
}
}
class Bill {
int amount;
public Bill( String amount ) {
amount = Integer.parseInt();
}
}
abstract class BaseHandler {
public List produceSomeStuff( String condition ) {
List result = new ArrayList();
// .. do stuff in a loop
result.add( make( condition ));
// .. do more stuff
return result;
}
public abstract Object make( String attribs );
}
public class CustomerHandler extends BaseHandler {
public List<Customer> getSomeCustomer( String condition ) {
List<Customer> result;
List resObj = produceSomeStuff( condition );
// make List<Customer> from resObj;
result = resObj; // unchecked
return result;
}
public Customer make( String attribs ) {
return new Customer( attribs );
}
}
public class BillHandler extends BaseHandler {
public List<Bill> getSomeBill( String condition ) {
List<Bill> result;
List resObj = produceSomeStuff( condition );
// make List<Bill> from resObj;
result = resObj;
return result;
}
public Bill make( String attribs ) {
return new Bill( attribs );
}
}
I can do all this and it works. But I get the unchecked messages from the compiler. The generics tutorial says one should not use the raw types any more. But I dont know what raw type to return from the BaseHandler produceSomeStuff method?
I tried List<?> but I couldnt convert into List<Customer>. I tried to pass Customer.class or Bill.class around to the BaseHandler and then back to
the make method, but then the make method became very ugly.
Do I have to copy the List<Object> one by one into a List<Customer> in order
to use generics as they are meant to be used? Is there a way with type
variables in the BaseClass to achieve what I want?
Arne
# 3
The code you provided still didn't compile... but how's this:
class Customer {
String name;
public Customer(String name) {
this.name = name;
}
}
class Bill {
int amount;
public Bill(String amount) {
this.amount = 0;
}
}
abstract class BaseHandler<T> {
public List<T> produceSomeStuff(String condition) {
List<T> result = new ArrayList<T>();
// .. do stuff in a loop
result.add(make(condition));
// .. do more stuff
return result;
}
public abstract T make(String attribs);
}
public class CustomerHandler extends BaseHandler<Customer> {
public List<Customer> getSomeCustomer(String condition) {
return produceSomeStuff(condition);
}
@Override
public Customer make(String attribs) {
return new Customer(attribs);
}
}
class BillHandler extends BaseHandler<Bill> {
public List<Bill> getSomeBill(String condition) {
return produceSomeStuff(condition);
}
@Override
public Bill make(String attribs) {
return new Bill(attribs);
}
}
# 4
Hello again and sorry for the delay, it was nighttime here in Greece.
I haven't actually thought of putting the type parameter into the baseclass definition. I only tried putting it into the method definition.
I put that to lack of experience with generics ..
Your solution looks right, I try it with my actual code and send the points over afterwards.
Thanks a lot