Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Producing an abstract collection from an abstract collection

This issue has been bugging me for a while. Abstractly speaking, regardless of language, there are often situations when you want to have a method like this:

Collection method(Collection c) {
    // select some elements from c based on some filter 
    // and return a new collection
}

Now, Collection is in this case some abstract class (Like say IList in C# or List in Java) with several implementations. I've been wondering what exactly is the right procedure to produce the abstract collection?

Is it ok to create a concrete collection inside the method and return it? Like:

Collection method(Collection c) {
   Collection cc = new ConcreteCollection();
   // select some elements from c based on some filter 
   return cc;
}

This of course puts a constraint on the resulting collection and will produce problems in case, for some reason, we want to cast the result of the method to a different concrete collection than the one used inside the method.

Or, use reflection to determine the actual concrete type of c and create an instance of that class:

Collection method(Collection c) {
   Collection cc = c.getClass().newInstance();
   // select some elements from c based on some filter 
   return cc;
}

For some reason this does not seem very "elegant" to me. I would greatly appreciate some insight in this matter.

like image 622
Tudor Avatar asked Feb 22 '23 06:02

Tudor


2 Answers

(Speaking for java). The reason you're returning Collection (an interface) rather than a concrete type (such as ArrayList) is that you're telling the user that they shouldn't care about what the actual concrete type being used is. This leaves you free to choose the appropriate type for your library/api.

If you're enforcing a particular concrete class, then you should be returning that concrete class, rather than the interface.

So, they shouldn't be casting your return type to anything else other than Collection. See When should I return the Interface and when the concrete class?.

like image 53
Matthew Farwell Avatar answered Mar 16 '23 15:03

Matthew Farwell


In Java, there are actually some good examples of how to do this in the java.util.Collections class. Instead of taking a Collection and returning a Collection, the key methods take two collections, the "src" and the "dest". For example, Look at the signature of the copy method:

public static <T> void copy(List<? super T> dest, List<? extends T> src)

This puts the responsibility of instantiating the destination list on the caller.

I think you could do the same thing when you want to create a method that acts on a src Collection and puts the results into a destination Collection (rather than Lists).

I agree with Matthew Farwell's answer that you probably just want to return the interface and utilize that, but for the times when you really do need to work with a specific implementing class you can do it the same way the Collections class does it.

like image 30
Jeff Goldberg Avatar answered Mar 16 '23 17:03

Jeff Goldberg