I know that in Java most people declare a list using:
List l = new ArrayList();
But what would be the difference between that and
AbstractList l = new ArrayList();
What are the advantages of using an interface over an abstract class in this particular instance?
Original answer:
An abstract class allows you to define some shared functionality, while leaving other functionality to be defined by implementations. Thus, abstract classes are useful if you are going to create a family of similar classes that share some functionality but have customizations.
An interface doesn't allow you to define any functionality. It simply defines a set of method signatures that you know can be called on any object of a class that implements that interface.
I'd say the accepted practice is not to use an abstract class to fill the role of an interface. That is, an abstract class should be used for code sharing among related classes that you define, whereas an interface should be used for abstraction.
One reason not to use abstract classes to fill the role of interfaces is that a class cannot inherit from more than one class, but it can implement many interfaces. Thus, using abstract classes limits your design a lot more than using interfaces does.
Edit:
In this particular instance, the difference would be that if you later reassigned l to contain an object that implements List but does not derive from AbstractList, your code will throw an exception. Not all classes that implement List also extend AbstractList.
Using AbstractList limits you to only working with lists that are derived from the core AbstractList functionality. On the other hand, anyone could write a class that implements List using totally new code, and if you're using a variable of type List then you'll still be compatible with their new class that you've never seen before.
The fact that Java's lists are derived from AbstractList should be treated as an implementation detail that's internal to the Java library, not as an interface that you should code against.
The hierarchy is like...
ArrayList extends AbstractList implements List
and
AbstractList implements List
So,
whenever you are creating a object of ArrayList like given below, You will be creating object of ArrayList with reference of List
List list = new ArrayList();
Another thing to note is, why it is required to implement List in both class,
So,
it is for the purpose of showing that ArrayList implements List.
AbstractList in the whole picture is just for convenience and to
reduce code duplication between List implementations.
Reference: This SO Answer
In this case it wouldn't be really different. However it's a common code style to use the interface as the variable type, as the abstract implementation of AbstractWhatever class is mean to make it easier to create an implementation without having to implement all of the methods in the interface.
So it's a style issue, not really a technical one.
Related
It's all about terminology. Can I say that the List is an abstract data type and the ArrayList is a data structure? So, the Java Collection Framework is group of ASTs and corresponding DSs (implementations).
An interface (not only in Java, but also in e.g. C#, Go etc.) is a definition of the API, a contract, that specifies which methods can be invoked on instances implementing the interface. Interfaces neither hold any data nor actually implement the contract themselves. In that sense one can say that an interface is an abstract data structure. List is an interface, that is it is a contract describing how one can operate with an ordered collection of data. An interface can extend another interface with further contract methods. As the List interfaces describes an ordered collection of data it makes perfect sense that it extends the Collection interface, which simply defines a contract for a generic collection of data (e.g. without referring to a specific ordering or insertion rules). Again, one can describe that as an abstract data structure.
ArrayList is one of possible implementations of the List interface. As such it also implements the Collection interface. So it is a concrete data structure (and a collection itself) implementing more than one abstract data structures. However, there are also abstract classes in Java, those which have some methods left unimplemented. These are also abstract data structures, but are not interfaces. So an interface in Java is an abstract data structure, but not vice versa.
Furthermore, one can have an abstract data structure (abstract class) implementing an interface (an abstract data structure itself). A thought exercise for you: figure what is the meaning of that :)
But then, what is abstract? A concrete class parametrized with a generic type is in a way an abstract data structure as it abstracts away algorithms applicable to different classes that can be used to subsitute the generic type. As ArrayList is itself one of those concrete implementations that uses Java generics to define the data type it operates on, it is itself an abstract data structure, but in a different way from interfaces or abstract classes. The abstract data structure is, in this sense, an ill-defined term.
List is an Interface. You always have an implementation behind it, and you cannot go like:
List list = new List(); // does not work. At least not with java.util.List
ArrayList is one of the implementations that implements the List interface.
So, thus said, you could put it that way.
Why do many Collection classes in Java extend the Abstract class and also implement the interface (which is also implemented by the given abstract class)?
For example, class HashSet extends AbstractSet and also implements Set, but AbstractSet already implements Set.
It's a way to remember that this class really implements that interface.
It won't have any bad effect and it can help to understand the code without going through the complete hierarchy of the given class.
From the perspective of the type system the classes wouldn't be any different if they didn't implement the interface again, since the abstract base classes already implement them.
That much is true.
The reason they do implement it anyways is (probably) mostly documentation: a HashSet is-a Set. And that is made explicit by adding implements Set to the end, although it's not strictly necessary.
Note that the difference is actually observable using reflection, but I'd be hard-pressed to produce some code that would break if HashSet didn't implement Set directly.
This may not matter much in practice, but I wanted to clarify that explicitly implementing an interface is not exactly the same as implementing it by inheritance. The difference is present in compiled class files and visible via reflection. E.g.,
for (Class<?> c : ArrayList.class.getInterfaces())
System.out.println(c);
The output shows only the interfaces explicitly implemented by ArrayList, in the order they were written in the source, which [on my Java version] is:
interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
The output does not include interfaces implemented by superclasses, or interfaces that are superinterfaces of those which are included. In particular, Iterable and Collection are missing from the above, even though ArrayList implements them implicitly. To find them you have to recursively iterate the class hierarchy.
It would be unfortunate if some code out there uses reflection and depends on interfaces being explicitly implemented, but it is possible, so the maintainers of the collections library may be reluctant to change it now, even if they wanted to. (There is an observation termed Hyrum's Law: "With a sufficient number of users of an API, it does not matter what you promise in the contract; all observable behaviors of your system will be depended on by somebody".)
Fortunately this difference does not affect the type system. The expressions new ArrayList<>() instanceof Iterable and Iterable.class.isAssignableFrom(ArrayList.class) still evaluate to true.
Unlike Colin Hebert, I don't buy that people who were writing that cared about readability. (Everyone who thinks standard Java libraries were written by impeccable gods, should take look it their sources. First time I did this I was horrified by code formatting and numerous copy-pasted blocks.)
My bet is it was late, they were tired and didn't care either way.
From the "Effective Java" by Joshua Bloch:
You can combine the advantages of interfaces and abstract classes by adding an abstract skeletal implementation class to go with an interface.
The interface defines the type, perhaps providing some default methods, while the skeletal class implements the remaining non-primitive interface methods atop the primitive interface methods. Extending a skeletal implementation takes most of the work out of implementing an interface. This is the Template Method pattern.
By convention, skeletal implementation classes are called AbstractInterface where Interface is the name of the interface they implement. For example:
AbstractCollection
AbstractSet
AbstractList
AbstractMap
I also believe it is for clarity. The Java Collections framework has quite a hierarchy of interfaces that defines the different types of collection. It starts with the Collection interface then extended by three main subinterfaces Set, List and Queue. There is also SortedSet extending Set and BlockingQueue extending Queue.
Now, concrete classes implementing them is more understandable if they explicitly state which interface in the heirarchy it is implementing even though it may look redundant at times. As you mentioned, a class like HashSet implements Set but a class like TreeSet though it also extends AbstractSet implements SortedSet instead which is more specific than just Set. HashSet may look redundant but TreeSet is not because it requires to implement SortedSet. Still, both classes are concrete implementations and would be more understandable if both follow certain convention in their declaration.
There are even classes that implement more than one collection type like LinkedList which implements both List and Queue. However, there is one class at least that is a bit 'unconventional', the PriorityQueue. It extends AbstractQueue but doesn't explicitly implement Queue. Don't ask me why. :)
(reference is from Java 5 API)
Too late for answer?
I am taking a guess to validate my answer. Assume following code
HashMap extends AbstractMap (does not implement Map)
AbstractMap implements Map
Now Imagine some random guy came, Changed implements Map to some java.util.Map1 with exactly same set of methods as Map
In this situation there won't be any compilation error and jdk gets compiled (off course test will fail and catch this).
Now any client using HashMap as Map m= new HashMap() will start failing. This is much downstream.
Since both AbstractMap, Map etc comes from same product, hence this argument appears childish (which in all probability is. or may be not.), but think of a project where base class comes from a different jar/third party library etc. Then third party/different team can change their base implementation.
By implementing the "interface" in the Child class, as well, developer's try to make the class self sufficient, API breakage proof.
In my view,when a class implements an interface it has to implement all methods present in it(as by default they are public and abstract methods in an interface).
If we don't want to implement all methods of interface,it must be an abstract class.
So here if some methods are already implemented in some abstract class implementing particular interface and we have to extend functionality for other methods that have been unimplemented,we will need to implement original interface in our class again to get those remaining set of methods.It help in maintaining the contractual rules laid down by an interface.
It will result in rework if were to implement only interface and again overriding all methods with method definitions in our class.
I suppose there might be a different way to handle members of the set, the interface, even when supplying the default operation implementation does not serve as a one-size-fits-all. A circular Queue vs. LIFO Queue might both implement the same interface, but their specific operations will be implemented differently, right?
If you only had an abstract class you couldn't make a class of your own which inherits from another class too.
Suppose for a program that I needed a List of some kind. Any kind of List will do, so I create one.
List<Integer> example = new LinkedList<Integer>();
I've heard that it's good practice, when instantiating your objects, to define them as interfaces, if you are doing something that requires the use of that interface, but not necessarily that specific concrete class. For example, I could have made that "example" list an ArrayList instead.
However, defining my LinkedList to be a List interface in this way limits me. I can't use any of the LinkedList-specific methods, for example. I can only use methods that are in the List interface itself. The only way I've found to use my LinkedList-specific methods are to cast example to a LinkedList, like so:
((LinkedList)example).addLast(1);
...which seems to defeat the purpose, since by casting "example" to be a LinkedList, I may as well have created it and defined it to be a LinkedList in the first place, instead of a List.
So why is it good practice to create concrete classes and define them via interface? Is there something that I am missing?
LinkedList implements several interfaces.
The method addLast() comes from the Deque interface. It could be that's the interface you want to use.
Alternatively you might just need a List, in which case the add() method will append to the list.
I just met an strange case when reading the Java doc. Here is the link to Oracle's java doc on Arrays.asList method, http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...)
There is an example in the doc
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
My question is, as List is an interface, why can we declare stooges as a 'List', rather than a concrete subclass implementing List(e.g. ArrayList or LinkedList)?
So does it mean that we can have a reference variable of interface type? It looks quit weird to me as I always think that interface stands only for polymorphism, and we should never really use a interface type variable.
Could anyone please give me some clue on this?
Think of the List interface as a guarantee. Any class that implements List will be guaranteed to have the methods of the interface. When Arrays.asList() returns a List you're not actually getting an interface, you're getting a concrete class that is guaranteed to implement the methods listed in the List interface.
As to your "we should never really use a interface type variable" you're actually suppose to do that. It's called "programming to the interface". It's much more flexible if you can return a List as opposed to something like a LinkedList. The caller of your method isn't coupled to your specific implementation internal implementation which might use, and return, a LinkedList. If at some point you wanted to return a ArrayList instead of the LinkedList the caller would not have to change any code because they only care about the interface.
What does it mean to "program to an interface"?
Just a word of note, Serializable is a marker interface and a little odd because of that. It doesn't guarantee that methods are there, but instead guarantees that the creator of the class that implements serializable has thought about the many issues associated with serializing a class (overriding readObject/writeObject, compatiblity with other serialized forms, and other issues http://www.javapractices.com/topic/TopicAction.do?Id=45). So Serializable is still offering a guarantee, like List is, but it isn't about method signatures, it's about an extralinguistic feature of the language.
http://en.wikipedia.org/wiki/Marker_interface_pattern
Using an Interface as a reference type is a perfectly valid practice in Java. For example, the Serializable interface will do this inside it's class, so that any object that is passed to it can be serialized.
This is also how Java provides something that resembles Multiple Inheritance. For example:
public interface A { }
public class B implements A {}
public class program {
B bClass = new B();
A aObject = (A)bClass;
}
That way the same object can be referenced with different reference types, and all without messing up an inheritance chain!
The interface defines a contract or a specification for an implementation. Which is the methods and their signature. So a class that implements an interface has to respect that contract. This way you can change implementation without affecting the code that uses interfaces for declaring variables.
In the example you mentioned:
You don't know what implementation of the List interface Arrays.asList is using unless you look into the code. So how would you know which one to use? (see javadoc for list interface to see what implementations it has)
The implementation is subject for change, what if Arrays.asList decides to use another implementation? Your code will be broken.
The signature of the method Arrays.asList is that it returns List<T> so if you want to have a concrete implementation as variable you'll have to cast that return value which is bad practice or to create new - let's say ArrayList - and copy all the elements into it, which is just an unnecessary overhead.
Effective Java by Bloch is a great book on Java best practices. In particular, item #52 talks about this: "If the appropriate interface types exist ... declared using the interface types."
The general notion is that, for greatest flexibility and understandability, you should use the type that best reflects the context, which is usually the interface. In the example, you provided, does the exact implementation matter or just that it is a List. Of course, if the code requires an ArrayList-specific method or if the code is relies on an ArrayList-specific behavior, then use the concrete class.
There are occasional exceptions, such as when using GWT-RPC, but this is for implementation reasons.
This is really good example of polymorphism power, if you like you can look at the source code of Arrays.asList() here Arrays.asList(T...a) ,you will find that it takes varibale length input and defines its own private static concrete class ArrayList that implements List interface rather than using the well known java.util.ArrayList or other java Collection type,
this may be to make it more efficient or something, you want to implement your own class and you return it to the user without overwhelming him by implementation details since there is an interface he can deal with your private class through.
I need to develop interface which can be implemented only once. If other class try to implement same interface in same project then it should not be allowed or give an error.
interface A {
void someMethod();
}
class B implements A {
void someMethod() {
// implementation here
}
}
Now I want to restrict other classes to implement interface A
class c implements A { //this should not allowed in this project
}
Is it possible to develop this kind of interface? Can anyone suggest, how can I go through to achieve this?
Simple answer, no it is not possible if your interface is public/package protected.
This defeats the purpose of an interface. If you're only going to have one implementation, it may as well be concrete.
Interfaces are meant to be implemented by multiple classes. This allows you to switch out implementations without having to worry about their implementation details. For example, the most common use of interfaces is with the collections framework, particularly List, Set, and Map.
// Hides the implementation details of ArrayList within a List variable
List<String> strs = new ArrayList<String>();
// Hides the implementation details of LinkedList within the same List variable
strs = new LinkedList<String>();
// All code using strs is agnostic to what kind of list it is (mostly)
strs.add("Hello, Dolly");
System.out.println(strs.get(0));
Interfaces primarily embody two OOP concepts: encapsulation and polymorphism. If you don't plan on using your interface to accomplish one of these two things, don't use an interface. Just use a concrete (non-abstract) class. Using an interface at this point is overkill.
Only exception to this rule I can think of is when you want to use Java's Proxy class. Only then is a 1:1 interface:class ratio acceptable since you have to have an interface to wrap the implementation in the Proxy instance.
It sounds like your design is wrong, and that your interface should actually just be part of class B.
The point of an interface is that it allows different implementations of the same set of methods, which you are trying to avoid here.
Put your interface A with class B in same package.
All the classes which should not implement A, should be outside this package.
The only global way to know about implementations of A is if they register themselves to you, which is pointless, you can forget about that.
I'm not sure if you require that all instances of A that you work with have a common class besides Object.class, or that their class is the same, or that their class is B.class.
Regardless of what you want to enforce, you need to test for undesirable situations on instances of A that you get passed, you have no business with instances of A that you don't work with anyway.
Alternatively, for every instance of A you get passed, you could create a new B and insert the data that you need from the passed A.
But first, you should think about why you want this, chances are it's not really a problem when there are different implementations of A.