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]
# 1
Assuming A and B are classes (which is a dreadful idea on a generics forum where we expect single upper-case letters to represent type parameters), then there is nothing to stop you doing new A() and new B() ever. Can you be more specific about what you've tried and what happened?
dannyyatesa at 2007-7-12 9:03:50 > top of Java-index,Core,Core APIs...
# 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

DoneThata at 2007-7-12 9:03:50 > top of Java-index,Core,Core APIs...
# 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);

}

}

dannyyatesa at 2007-7-12 9:03:50 > top of Java-index,Core,Core APIs...
# 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

DoneThata at 2007-7-12 9:03:50 > top of Java-index,Core,Core APIs...
# 5
... it compiles with no warnings and type safety. Hurraay to generics, and to dannyyates :-)
DoneThata at 2007-7-12 9:03:50 > top of Java-index,Core,Core APIs...