Collection of objects of all classes which implement a particular interface - java

I have an interface TestInterface and different classes may implement the interface. Is it possible to have a collection of all the objects which implements the interface? The collection can be created using
LinkedList<TestInterface> store
where store is the name of the collection. But how to keep track of the object creations of classes which implement the TestInterface. And moreover where to keep the collection?

Not knowing what you want this for, it's hard to tell.
But anyway, yes you can create a collection but in order to track and store references to the TestInterface objects, you must control their creation.
The easiest way would be to have a TestInterfaceFactory (see AbstractFactory pattern), this is also a good place to keep the store collection with the instance references.

Is it possible to have a collection of all the objects which implements the interface?
In theory yes.
In reality, it will only work if everything that creates an instance of the object also adds it to the list. And that probably makes it impractical ... unless you change the way the objects are created.
One approach use factories, but there is nothing to stop some code creating an instance without using your carefully implemented factory.
Another approach would be to replace the interface with an abstract base class whose constructor(s) guarantee that every new instance is added to the list. This can't be subverted using normal code. However, if you use Java Object Serialization (or similar) you'll need to put a "hook" into the base class to make sure that deserialized objects are added to the list.
Note that a collection that contains all instances of some interface or class is potentially a huge memory leak. You'll probably need to do something about this; e.g. using weak references.

If you desperately need to make this automatic, then in principle, you could:
use the Java instrumentation framework, adding a ClassFileTransformer to ensure that any class implementing your interface is redefined to have its constructors automatically add instances to your collection (look at something like the Bytecode Engineering Library, BCEL, if you were to go down this route);
possibly easier but still quite a lot of work: use the JVM Tool Interface to write an agent that can query the heap on the fly for instances of your object.
Either way, if the interface is yours, then introducing a programming convention whereby all instances of implementations of that interface are added to the collection is definitely easier, if more error-prone.

Related

Inheritance, composition and default methods

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 scratch) is more maintenable.
This works because the interface contract forces the user to implement all the desired functionality. However in java 8, default methods provide some default behavior which can be "manually" overriden. Consider the following example : I want to design a user database, which must have the functionalities of a List. I choose, for efficiency purposes, to back it by an ArrayList.
public class UserDatabase extends ArrayList<User>{}
This would not usually be considered great practice, and one would prefer, if actually desiring the full capabilities of a List and following the usual "composition over inheritance" motto :
public class UserDatabase implements List<User>{
//implementation here, using an ArrayList type field, or decorator pattern, etc.
}
However, if not paying attention, some methods, such as spliterator() will not be required to be overridden, as they are default methods of the List interface. The catch is, that the spliterator() method of List performs far worse than the spliterator() method of ArrayList, which has been optimised for the particular structure of an ArrayList.
This forces the developer to
be aware that ArrayList has its own, more efficient implementation of spliterator(), and manually override the spliterator() method of his own implementation of List or
lose a huge deal of performance by using the default method.
So the question is : is it still "as true" that one should prefer composition over inheritance in such situations ?
Before start thinking about performance, we always should think about correctness, i.e. in your question we should consider what using inheritance instead of delegation implies. This is already illustrated by this EclipseLink/ JPA issue. Due to the inheritance, sorting (same applies to stream operation) don’t work if the lazily populated list hasn’t populated yet.
So we have to trade off between the possibility that the specializations, overriding the new default methods, break completely in the inheritance case and the possibility that the default methods don’t work with the maximum performance in the delegation case. I think, the answer should be obvious.
Since your question is about whether the new default methods change the situation, it should be emphasized that you are talking about a performance degradation compared to something which did not even exist before. Let’s stay at the sort example. If you use delegation and don’t override the default sorting method, the default method might have lesser performance than the optimized ArrayList.sort method, but before Java 8 the latter did not exist and an algorithm not optimized for ArrayList was the standard behavior.
So you are not loosing performance with the delegation under Java 8, you are simply not gaining more, when you don’t override the default method. Due to other improvements, I suppose, that the performance will still be better than under Java 7 (without default methods).
The Stream API is not easily comparable as the API didn’t exist before Java 8. However, it’s clear that similar operations, e.g. if you implement a reduction by hand, had no other choice than going through the Iterator of your delegation list which had to be guarded against remove() attempts, hence wrap the ArrayList Iterator, or to use size() and get(int) which delegate to the backing List. So there is no scenario where a pre- default method API could exhibit better performance than the default methods of the Java 8 API, as there was no ArrayList-specific optimization in the past anyway.
That said, your API design could be improved by using composition in a different way: by not letting UserDatabase implement List<User> at all. Just offer the List via an accessor method. Then, other code won’t try to stream over the UserDatabase instance but over the list returned by the accessor method. The returned list may be a read only wrapper which provides optimal performance as it is provided by the JRE itself and takes care to override the default methods where feasible.
I don't really understand the big issue here. You can still back your UserDatabase with an ArrayList even if not extending it, and get the performance by delegation. You do not need to extend it to get the performance.
public class UserDatabase implements List<User>{
private ArrayList<User> list = new ArrayList<User>();
// implementation ...
// delegate
public Spliterator() spliterator() { return list.spliterator(); }
}
Your two points are not changing this. If you know "ArrayList has its own, more efficient implementation of spliterator()", then you can delegate it to your backing instance, and if you do not know, then the default method takes care of it.
I am still unsure whether it really makes any sense to implement the List interface, unless you are explicitly making a reusable Collection library. Better create your own API for such one-offs that does not come with future problems through the inheritance (or interface) chain.
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<User> list = new ArrayList<>();
public Stream<User> 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.
The selection is simple based on your requirement.
Note - The below is just a use case . to illustrate the difference.
If you want a list that is not going to keep duplicates and going to do a whole bunch of things very much different from ArrayList then there is no use of extending ArrayList because you are writing everything from scratch.
In the above you should Implement List. But if you are just optimizing an implementation of ArrayList then you should copy paste the whole implementation of ArrayList and follow optimization instead of extending ArrayList. Why because multiple level of implementation makes it difficult for someone tries to sort out things.
Eg: A computer with 4GB Ram as parent and Child is having 8 GB ram. It is bad if parent has 4 GB and new Child has 4 GB to make an 8 GB. Instead of a child with 8 GB RAM implementation.
I would suggest composition in this case. But it will change based on the scenario.
It is usually admitted that extending implementations of an interface through inheritance is not best practice, and that composition (e.g. implementing the interface again from scratch) is more maintainable.
I don't think that this is accurate at all. For sure there are lots of situations where composition is preferred over inheritance, but there are lots of situations where inheritance is preferred over composition!
Its especially important to realise that the inheritance structure of your implementation classes need not look anything like the inheritance structure of your API.
Does anyone really believe, for example, that when writing a graphical library like Java swing every implementation class should reimplement the paintComponent() method? In fact a whole principal of the design is that when writing paint methods for new classes you can call super.paint() and that insures that all elements in the hierarchy are drawn, as well as handling the complications involving interfacing with the native interface further up the tree.
What is generally accepted is that extending classes not within your control that were not designed to support inheritance is dangerous and potentially a source of irritating bugs when the implementation changes. (So mark your classes as final if you reserve the right to change your implementation!). I doubt Oracle would introduce breaking changes into ArrayList implementation though! Provided you respect its documentation you should be fine....
Thats the elegance of the design. If they decide that there is a problem with the ArrayList, they will write a new implementation class, similar to when they replaced Vector back in the day, and there will be no need to introduce breaking changes.
===============
In your current example, the operative question is: why does this class exist at all?
If you are writing a class which extends the interface of list, which other methods does it implement? If it implements no new methods, what is wrong with using ArrayList?
When you know the answer that you will know what to do. If the answer "I want an object which is basically a list, but has some extra convenience methods to operate on that list", then I should use composition.
If the answer is "I want to fundamentally change the functionality of a list" then you should use inheritance, or implement from scratch. An example might be implementing an unmodifiable list by overriding ArrayList's add method to throw an exception. If you are uncomfortable with this approach you might consider implementing from scratch by extending AbstractList, which exists precisely to be inherited from to minimise the effort of reimplementation.

What is detailed explanation of argument "Subclass Only Where It Makes Sense"?

From presentation called How to Design a Good API and Why it Matters
I'm stuck on page 25 of the presentation in which says:
Public classes should not subclass other public classes for ease of
implementation
And it gave us an examples (Java syntax):
Bad: Properties extends Hashtable
Stack extends Vector
Good: Set extends Collection
But why are those examples bad and good?
Because a Properties is not a Hashtable, and they shouldn't be used interchangeably, i.e., you don't want users to use Properties where they only need Hashtable. Same for Stack vs Vector.
Good design should strive for simplicity of API. If you are designing a Stack, you should basically only provide the push and pop methods. Publicly inheriting from Vector leaks an implementation detail that the user does not need to know. Beside the confusion, this means you can never change the implementation! So if tomorrow Vector gets deprecated (which I believe it actually is at this point), you are still stuck with a Stack that uses it because your clients might expect it. Changing the implementation would violate backward compatibility, which is another design goal.
Note that the example above is not random. Both Vector and Hashtable are classes that are considered obsolete (see the last comments here and here). These classes have some design flaws and were replaced by ArrayList and HashMap or similar others. This makes classes that inherit from them obsolete as well. If instead of inheriting you used composition, you could easily swap Vector and Hashtable for their modern counterparts without affecting any user.
On the other hand, Set is a Collection. That is, if some code specifies that it needs some kind of Collection, the user is free to provide a Set (or a List or whatever). This gives more flexibility to the API if there are no specific requirements on what this collection should provide (no random access for example).
Inheriting from a class is typically thought of as implementing an "is-a" relationship.
Is a collection of properties a hashtable? No, not really. The hashtable is an implementation detail, not a fundamental characteristic of "Properties". This implies that you should be using aggregation, like so:
class Properties {
private HashTable mPropertyTable;
}
The same goes for Stack and Vector. A Stack isn't a special kind of Vector, so the Vector should be a member of the Stack used for implementation only.
Contrast this with Set deriving from Collection. Is a Set a type of Collection? Yes, it is, so in this case inheritance makes sense.
Bloch is distinguishing inheritance of interface from inheritance of implementation.
It is impossible to know from a slide deck what he said at this point in his presentation, but a typical argument for avoiding one public class inheriting from another is that it permanently ties the subclass to the superclass's implementation. For example, Properties cannot ever implement its property storage in HashMap form or any other form other than a HashTable.
Another argument is that it couples the classes too tightly together. Modifications that would be beneficial to the superclass can break the subclass, or render its behavior worse.
A third argument is that the subclass inherits methods from the superclass that may not make sense for it, or may do so in the future if the methods are added to the superclass. For example, because Stack extends Vector, it is possible to examine arbitrary elements below the top one, and even to add, remove, or modify internal elements. This one applies to some extent also to inheritance of interface, but it is not usually as much of a problem in that case.
The first two arguments remain applicable to some extent even when the super- and subclasses have an is-a relationship.

Empty interfaces - Modeling of object relationships

Is it ok to use empty interfaces for object modeling?
E.g. the following interface extends other empty interfaces in order the characterize the object 'Ferry':
public interface Ferry extends Watercraft, StationBased, Scheduled, Oneway, Motorized {}
Watercraft, StationBased, etc., are all empty interfaces, too, so they kind of act as a marker. However, they are not used by the JVM or compiler. These classes are only used for modeling purposes.
Is this good practice? Should an interface not usually provide some kind of common functionality, and not merely mark a class?
Yes, you can use empty interfaces for object modeling, but... Object modeling without any use-case is IMO overstretching it.
You write code to execute concrete actions, you model it to leverage general abstractions in the domain, and yes you can over-abstract your code.
Adding an interface in code is a classification or typification, which is only necessary as long as there is a taker for it. Otherwise it is plain dead code.
My worst encounter which sometimes still haunts me in my nightmares was an abstraction over business services, which essentially replaced it with a single method taking a map as arguments and returning an object which either contained the result or an error state. Effectively modeling a method invocation, but this time without types. Having forced this down on all business methods was simply a nightmare to unravel later.
There is nothing wrong with doing it that way except that you may discover quite quickly that changing the structure or adding new forms will become unpleasant.
I would probably consider a much more flexible enum option.
enum CraftAttributes {
Watercraft,
StationBased,
Scheduled,
Oneway,
Motorized;
}
class Ferry {
Set<CraftAttributes> attributes = EnumSet.of(
CraftAttributes.Watercraft
//...
);
}
There are lots of sweet thing you can do with unions and intersections of Sets that make for powerful but lucid code.

Java Variable type and instantiation

This has been bugging me for a while and have yet to find an acceptable answer. Assuming a class which is either a subclass or implements an interface why would I use the Parent class or Interface as the Type i.e.
List list = new ArrayList();
Vehicle car = new car();
In terms of the ArrayList this now only gives me access to the List methods. If I have a method that takes a List as a parameter then I can pass either a List or an ArrayList to it as the ArrayList IS A List. Obviously within the method I can only use the List methods but I can't see a reason to declare it's type as List. As far as I can see it just restricts me to the methods I'm allow to use elsewhere in the code.
A scenario where List list = new ArrayList() is better than ArrayList list = new ArrayList() would be much appreciated.
You write a program that passes lists around several classes and methods. You now want to use it in a multi threading environment. If you were sensible and declared everything as List, you can now make a single change to one line of code:
List list = Colllections.synchronizedList(new ArrayList());
If you had declared the list as an ArrayList, you would instead have to re-write your entire program. The moral of the story - always program to the least restrictive interface that your code requires.
Using the interface or parent type is generally recommended if you only need the functionality of the parent type. The idea is to explicitly document that you don't really care about the implementation, thus making it easier to swap out the concrete class for a different one later.
A good example are the Java collection classes:
If you always use List, Set etc. instead of e.g. ArrayList, you can later switch from ArrayList to LinkedList if you find that it gives e.g. better performance. To do that, just change the constructors (you don't even have to change them all, you can mix). The rest of the code still sees an instance of List and continues working.
If you actually used ArrayList explicitly, you'd have to change it everywhere it's used. If you don't actually need an ArrayList specifically, there's nothing to be gained from using it over the interface.
That's why it's generally recommended (e.g. in "Effective Java" (J.Bloch), Item 52: "Refer to Objects by their interfaces".) to only use interfaces if possible.
Also see this related question: Why classes tend to be defined as interface nowadays?
The key is exactly that the interface or base class restricts what you can do with the variable. For example, if you refactor your code later to use another implementation of that interface or base class, you won't have anything to fear -- you didn't rely on the actual type's identity.
Another thing is that it often makes reading the code easier, e.g. if your method's return type is List you might find it more readable to return a variable of type List.
An interface specifies a contract (what does this thing do), an implementation class specifies the implementation details (how does it do it).
According to good OOP practice, your application code should not be tied to implementation details of other classes. Using an interface keeps your application loosely coupled (read: Coupling)
Also, using an interface lets client code pass in different implementations and apply the decorator pattern using methods like Collections.synchronizedList(), Collections.unmodifiableList() etc.
A scenario where List list = new
ArrayList() is better than ArrayList
list = new ArrayList() would be much
appreciated.
One concrete example: if it's a field declaration and you have a setList(), which of course should take a List parameter to be flexible.
For local variables (and fields with no setters), there is very little concrete benefit in using the interface type. Many people will do it anyway on general principle.
You were right. In these cases, the variables are fields or local variables, they are not public interface, they are implementation details. Implementation detail should be detailed. You should call an ArrayList an ArrayList, because you just deliberately chose it for your implementation.
People who recycle cliches: look at your post and think a little bit more. It's nonsense.
My previous answer that was downvoted to death:
Use interface or type for variable definition in java?

Why does the Collections class contain standalone (static) methods, instead of them being added to the List interface?

For all the methods in Collections that take a List as their first argument, why aren't those methods simply part of the List interface?
My intuition is: given a List object, that object itself should "know" how to perform on itself operations such as rotate(), shuffle(), or reverse(). But instead, as a Java programmer, I have to review both the methods in the List interface, as well as the static methods "over there" in the Collections class, to ensure I'm using a canonical solution.
Why were some methods placed as static standalone methods in the Collections class, instead of being added to the List interface (and presumably thus implemented by some existing or would-be base class)?
I'm trying to better understand the design decisions behind the Java collections framework.
Is there some compelling OO design principle here that I'm overlooking? Or was this distinction done simply for some practical, performance reason?
The point is that given suitable primitive operations (remove, set etc) a bunch of more high level operations (sort, shuffle, binary search) can be implemented once rather than being implemented by every single list implementation.
Effectively, java.util.Collections is like .NET's Enumerable class - full of general purpose methods which can work on any collection, so that they can share a single implementation and avoid duplication.
Rational Behind the List Interface's Methods
The List interface is a very core part of the Java runtime and is already a little onerous to fully implement all of the members when rolling out your own List implementations. So, adding extra methods that aren't directly related to the definition of a list is a bit extraneous. If you need those methods on a List implementation, why not subclass the interface and then require them?
If you where going to come along say in version 1.3 and add functionality to the List interface by adding new utility methods, you will break all past implementors of the interface.
From a Domain-Driven Design perspective, the utility methods in Collections are not part of the normal domain of a list.
Regarding OO design principals, I think it would be important to make the distinction between application OO design and language runtime OO design.
The authors of Java may do things very differently now that they have hindsight and perspective of many years of usage of the API. That said the C# IList interface is quite similar to Java's and C#'s authors did have the perspective.
It's certainly a judgement call at some level. I think the main trade-off to consider is this: When you add a method to an interface, every implementer of that interface must write code to implement it.
If the semantics of that method are such that different implementations of the interface will best implement those semantics in very different ways, then it's better to put it in the interface. (Of course, if the semantics simply can't be defined in terms of other methods in the interface, then it must be its own method in the interface.)
On the other hand, if the semantics are such that they can be defined in terms of other methods in the interface, and implementers of the interface will just tend to write the same code over and over again, then it's better to make a utility method that takes an instance of the interface as an argument.
They are utility methods and not core List functionality. The List interface would just get bloated if you added every possible operation you could do on a List. And the operations in Collections do not need to know about the internals of a List, they operate on the public interface so can happily live in an external class.
There are two explanations here:
Historical: Collections class was created after List interface. Designers chose to preserve backward compatibility of already existing interface. Otherwise a lot of developers would have to change their code.
Logical: The methods you are talking about do not require internal knowledge on List implementation and can be implemented over ANY collection implementing it.

Categories