How to extend a list in java to store additional metadata and force it to accept only one type of objects?

1k views Asked by At

In addition to the included items, I have to store the name and the id of the List inside itself. Thus i extended an ArrayList as follows:

class MyList<E> extends ArrayList<E>{
    private int id;
    private String name;

    MyList(int id, String name){
        this.id = id;
        this.name = name;
    }
    id getId(){       return id;   }
    String getName(){ return name; }
}

Now I realized, that this extension will only hold one specific type of objects. So how can I remove the generic character of my list?

class MyList<MyObject> extends ArrayList<E>
class MyList<MyObject> extends ArrayList<MyObject>

...and so on fails. I want to instantiate my list by

MyList mylist = new MyList();

...and it should automatically accept only MyObjects...

(Would it be better to create a wrapper which holds an ArrayList in addition to the meta? But because it is still a list, why remove all list-typical capabilities...)

2

There are 2 answers

0
Sotirios Delimanolis On BEST ANSWER

You'll need

class MyList extends ArrayList<MyObject>

When you declare a type parameter for your class declaration like so

class MyList<MyObject> ...

the type MyObject> is not your type, it is a type variable that also has the name MyObject.

What you want, is to use your MyObject type as a type argument for the ArrayList type parameter as shown above.


But, as others have suggested, composition is probably a better way to do this, ie the wrapper you suggested in your question.

2
afsantos On

As has been answered already, the correct declaration would be

class MyList extends ArrayList<MyObject>

Even though you have no interest in overriding any ArrayList methods, you should consider composition over inheritance for this type of scenarios.

Example:

class MyList implements Iterable<MyObject> {
    private final int id;
    private final String name;
    private final List<MyObject> list;

    MyList(int id, String name){
        this.id = id;
        this.name = name;
        this.list = new ArrayList<>();
    }

    int getId()                     { return id; }

    String getName()                { return name; }

    MyObject get(int i)             { return list.get(i); }

    void add(MyObject o)            { list.add(o); }

    void remove(MyObject o)         { list.remove(o); }

    void remove(int i)              { list.remove(i); }

    void set(int i, MyObject o)     { list.set(i, o); }

    boolean contains(MyObject o)    { return list.contains(o); }

    int size()                      { return list.size(); }

    @Override
    Iterator<MyObject> iterator()   { return list.iterator(); }
}

With this:

  • You can easily switch the ArrayList for a LinkedList, or any other list;
  • You control the methods this class offers;
  • If you like the chaining style, you may change those void for MyList;
  • etc.