I'm making a simple program that maintains a list of numbers, and I want this list to also have a name. Which is the best approach: have my list class extend ArrayList or have it include an ArrayList member? In both cases, there would of course be a "name" String member.
The first approach means I only have to implement a getter & setter for the name, but I think this would tie my class too closely to a particular implementation? For example, if I wanted to later use a Vector, than I would have to change code everywhere.
The second approach would make it easier to change the implementation, but of course becomes quite annoying for now, since I have to implement a bunch of wrappers.
I've read the SO posts regarding inheritance vs. composition, and since my list is a type of ArrayList, I am leaning towards the first approach. However, is there any differences to the discussion because I'm extending a Collection class vs extending a general class? Or am I over-thinking this?
As many other have said, yes, you can extend class ArrayList , but it is not something that you should normally do; it is not considered good practice in Java.
When you create an ArrayList you can specify the initial capacity. For example: ArrayList<Integer> arrayList = new ArrayList<>(100); In this case, the initial capacity of the ArrayList will be 100.
Approach: ArrayLists can be joined in Java with the help of Collection. addAll() method. This method is called by the destination ArrayList and the other ArrayList is passed as the parameter to this method. This method appends the second ArrayList to the end of the first ArrayList.
The size of an ArrayList can be obtained by using the java. util. ArrayList. size() method as it returns the number of elements in the ArrayList i.e. the size.
In the long run it's generally better to include as a member than extend. This way it's more explicit what you want to allow, making it easier to test and hold to the contact of the class. If you simply extend ArrayList then it might not always be used as you intended. The trade-off of course is that you'll have to explicitly create pass-through methods for everything you do want to allow. Alternatively (or additionally) you might want to provide a method to get the underlying List, which you could wrap with an immutable collection to safeguard it from changes happening outside of the control of your class.
For the best of both worlds, use a Guava ForwardingList. Here's a simple example:
public class NamedList<E> extends ForwardingList<E> implements RandomAccess {
// could also let the user provide the delegate list
private final List<E> delegate = Lists.newArrayList();
private String name;
@Override protected List<E> delegate() {
return delegate;
}
// constructors, getter, setter
}
By the way, the pitfalls of extending a concrete collection implementation rather than using composition are discuseed in Effective Java item 16 (in 2nd Ed.) "Favor composition over inheritance." One of the several issues mentioned has to do with unexpected behavior related to the interaction between methods in the superclass (e.g. add
and addAll
).
Guava's Forwarding*
classes are an implementation of the solution suggested there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With