It is usually admitted that extending implementations of an interface through inheritance is not best practice, and that composition (eg. implementing the interface again from s
I cannot provide an advice for every situation, but for this particular case I'd suggest not to implement the List
at all. What would be the purpose of UserDatabase.set(int, User)
? Do you really want to replace the i-th entry in the backing database with the completely new user? What about add(int, User)
? It seems for me that you should either implement it as read-only list (throwing UnsupportedOperationException
on every modification request) or support only some modification methods (like add(User)
is supported, but add(int, User)
is not). But the latter case would be confusing for the users. It's better to provide your own modification API which is more suitable for your task. As for read requests, probably it would be better to return a stream of users:
I'd suggest to create a method which returns the Stream
:
public class UserDatabase {
List list = new ArrayList<>();
public Stream users() {
return list.stream();
}
}
Note that in this case you are completely free to change the implementation in future. For example, replace ArrayList
with TreeSet
or ConcurrentLinkedDeque
or whatever.