Strongly Typing List and ArrayList - Generics?

I'm trying to solve a classic case. I want to create a custom List and ArrayList that work with only one type of object and provide some additional functionality related to that object.

Traditionally one would just extend List/ArrayList, create type-specific methods to work with the list and check for casting errors. I was wondering with the introduction of Generics if there was a simpler way of doing this WITHOUT having to recreate all of those add, indexOf, etc methods?

For example, assume I have a class:

publicclass Thingie{

protected String name;

public Thingie(String name){

super();

this.name = name;

}

public String getName(){

return name;

}

publicvoid setName(String name){

this.name = name;

}

}

And I have a List:

publicinterface ThingieListextends List{

publicvoid printAll();

}

And I have an ArrayList:

publicclass ThingieArrayListextends ArrayListimplements ThingieList{

publicvoid printAll(){

ListIterator iter = this.listIterator();

while (iter.hasNext()){

Thingie thingie = (Thingie) iter.next();

System.out.println(thingie.name);

}

}

}

And a simple class to use these objects:

publicclass ListTester{

publicstaticvoid main(String[] args){

ThingieList list =new ThingieArrayList();

list.add(new Thingie("One"));

list.add(new Thingie("Two"));

list.add(new Thingie("Three"));

list.add(new String(""));// Will cause an error, but is not detected

// by compiler

list.printAll();

}

}

Is there a way, using Generics or some other method to Make ThingieList and ThingieArrayList ONLY accept Thingies? Right now I can add any time of object to my ThingieList and won't get an error until runtime.

Thanks,

Leo

[3623 byte] By [leojhartiva] at [2007-11-26 17:58:29]
# 1

Two changes:

public interface ThingieList extends List<Thingie> {

...

}

public class ThingieArrayList extends ArrayList<Thingie> implements ThingieList {

...

}

But be aware, that extending ArrayList is bad design. Rather use delegation.

stefan.schulza at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 2
What do you mean. I'm definitely looking for a best practice for this sort of thing.
leojhartiva at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 3

Delegation would mean your class implements List<Thingie> but holds an internal variable of type List<Thingie>. The implementation of List<Thingie> having delegation methods. E.g.public class ThingieList implements List<Thingie> {

private final List<Thingie> list;

public ThingieList(List<Thingie> list) {

this.list = list;

}

public boolean add(Thingie o) {

return this.list.add(o);

}

...

}

The advantage is, that your class does not depend on internals of the delegatee. Of course, you can also hardcode to use an ArrayList<Thingie> internal.

stefan.schulza at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 4
I see what you're saying, but then I'd need to implement every method in the List interface just like I would pre-Generics, which is what I was trying to avoid.
leojhartiva at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 5
Well, your IDE should support that with a snap (at least eclipse and IDEA have support to create delegation methods). It's got nothing to do with Generics or not but design issues.
stefan.schulza at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 6
OK, thanks. I see I can also use the AbstractList class to cut down on alot of the work.
leojhartiva at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 7

What IDE are you using? Are you using an IDE?

In eclipse, creating all the methods you need:

- create the delegatee container (List<Thingie> myList)

- choose from context menu: Source > Generate Delegate Methods

- choose the delegatee and press OK

- done.

In IntelliJ IDEA it is similar. No work needed. No subclassing needed.

stefan.schulza at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 8
I use Eclipse and will try the approach you suggested.
leojhartiva at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...
# 9

in non-generics, the collection returns a Thingy rather than taking a Thingy argument, eg

public Thingy add() {

Thingy t = new Thingy();

this.collection.add( t );

return t;

}

mchan0a at 2007-7-9 5:11:48 > top of Java-index,Core,Core APIs...