Object-Oriented Design: Which is better practice? - java

I have a confusion in different ways the objects are created which I have seen in java docs and other programming books. For e.g.
Assuming there is a base class and a derived class
1- I have a variable of type Base which refers to the object of type Derived
List<String> list = new ArrayList<String>();
2- I have a variable of type Derived which refers to the object of type Derived
ArrayList<String> arrList = new ArrayList<String>();
My question is what should be my thinking while choosing between 1 and 2? Is it to take advantage of Polymorphism in general Base-Derived scenarios?
Is there a better practice while choosing between 1 and 2 that I am not aware of or is it just a personal decision?
EDIT:
Sorry, List is an interface.
Another question: Will my decision change if I use a Type parameter?
ArrayList<T> list = new ArrayList<T>();
Update Answer: This is actually called "Programming to the interface". Thanks Code-Guru. Exactly what I was looking for is explained in very simple terms in one of the answers to this question - What does it mean to "program to an interface"?

List is not a base class it is an interface and therefore should be used wherever possible.
Using the interface that a class implements allows you to work with all classes that implement the interface, not just the specific class.
String is a concrete class so it is much clearer to use it directly.
Sometimes, however, even though String implements the CharSequence interface it is unnecessary to use CharSequence because it would just be confusing. However, take a look at StringBuilder, it uses CharSequence almost exclusively.
In summary - there is no better there is just appropriate.

Choosing the base type allows you to at some point in the future change between using an ArrayList to say a LinkedList, without changing the rest of the code. This gives you more flexibility to refactor later on. Likewise, your public methods should return a List instead of the specific type of List implementation for the same reason -- so that you may change your internal implementation to optimize performance without breaking the contract to your callers.

In the case where List is a class ( just assume for the purpose of answering your question - "Shall we use object of Parent class representing child class or use object of type derived class ( actula class) ? "
1) You were correct, its solely for the purpose of polymorphism.
2) Mostly its used for Passing the object around different class methods. Other classes' methods may be accepting parent class a input. you have to use the casting in those places.

Related

What are the differences between these two object declarations which uses an Interface and a Class in Java? [duplicate]

PMD would report a violation for:
ArrayList<Object> list = new ArrayList<Object>();
The violation was "Avoid using implementation types like 'ArrayList'; use the interface instead".
The following line would correct the violation:
List<Object> list = new ArrayList<Object>();
Why should the latter with List be used instead of ArrayList?
Using interfaces over concrete types is the key for good encapsulation and for loose coupling your code.
It's even a good idea to follow this practice when writing your own APIs. If you do, you'll find later that it's easier to add unit tests to your code (using Mocking techniques), and to change the underlying implementation if needed in the future.
Here's a good article on the subject.
Hope it helps!
This is preferred because you decouple your code from the implementation of the list. Using the interface lets you easily change the implementation, ArrayList in this case, to another list implementation without changing any of the rest of the code as long as it only uses methods defined in List.
In general I agree that decoupling interface from implementation is a good thing and will make your code easier to maintain.
There are, however, exceptions that you must consider. Accessing objects through interfaces adds an additional layer of indirection that will make your code slower.
For interest I ran an experiment that generated ten billion sequential accesses to a 1 million length ArrayList. On my 2.4Ghz MacBook, accessing the ArrayList through a List interface took 2.10 seconds on average, when declaring it of type ArrayList it took on average 1.67 seconds.
If you are working with large lists, deep inside an inner loop or frequently called function, then this is something to consider.
ArrayList and LinkedList are two implementations of a List, which is an ordered collection of items. Logic-wise it doesn't matter if you use an ArrayList or a LinkedList, so you shouldn't constrain the type to be that.
This contrasts with say, Collection and List, which are different things (List implies sorting, Collection does not).
Why should the latter with List be used instead of ArrayList?
It's a good practice : Program to interface rather than implementation
By replacing ArrayList with List, you can change List implementation in future as below depending on your business use case.
List<Object> list = new LinkedList<Object>();
/* Doubly-linked list implementation of the List and Deque interfaces.
Implements all optional list operations, and permits all elements (including null).*/
OR
List<Object> list = new CopyOnWriteArrayList<Object>();
/* A thread-safe variant of ArrayList in which all mutative operations
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/
OR
List<Object> list = new Stack<Object>();
/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/
OR
some other List specific implementation.
List interface defines contract and specific implementation of List can be changed. In this way, interface and implementation are loosely coupled.
Related SE question:
What does it mean to "program to an interface"?
Even for local variables, using the interface over the concrete class helps. You may end up calling a method that is outside the interface and then it is difficult to change the implementation of the List if necessary.
Also, it is best to use the least specific class or interface in a declaration. If element order does not matter, use a Collection instead of a List. That gives your code the maximum flexibility.
Properties of your classes/interfaces should be exposed through interfaces because it gives your classes a contract of behavior to use, regardless of the implementation.
However...
In local variable declarations, it makes little sense to do this:
public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}
If its a local variable, just use the type. It is still implicitly upcastable to its appropriate interface, and your methods should hopefully accept the interface types for its arguments, but for local variables, it makes total sense to use the implementation type as a container, just in case you do need the implementation-specific functionality.
In general for your line of code it does not make sense to bother with interfaces. But, if we are talking about APIs there is a really good reason. I got small class
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
In this case is usage of interface required. Because I want to count size of every possible implementation including my own custom. class MyList extends AbstractList<String>....
Interface is exposed to the end user. One class can implement multiple interface. User who have expose to specific interface have access to some specific behavior which are defined in that particular interface.
One interface also have multiple implementation. Based on the scenario system will work with different scenario (Implementation of the interface).
let me know if you need more explanation.
The interface often has better representation in the debugger view than the concrete class.

Why can I use an interface as a type when creating a reference to an object?

I am following Oracle's online tutorial for Java and am puzzled by a particular line of code.
The full code for the example I am looking at is here: http://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
The particular line that bothers me is in the DataStructure class' printEven() method:
DataStructureIterator iterator = this.new EvenIterator();
I don't understand why the interface DataStructureIterator is used as the type for iterator when the actual type, EvenIterator, which I tried, works just as fine and makes more sense to me:
EvenIterator iterator = this.new EvenIterator();
It only make sense if your code must have an EvenIterator.
Otherwise the more-generalized interface should be preferred, allowing you to change the underlying implementation without any further code changes.
As a (somewhat contrived) concrete example, it might make sense to use only an ArrayList to enforce constant-time indexed access; in that case you might want to avoid the more-generalized List to make sure you don't blow up the timing of your app.
Interfaces are used to abstract the essence of the implementation in a neat type, and can and even should be used as references to the implementing types. This makes client classes agnostic of the real implementing classes, making the design more robust.
The example's choice of DataStructureIterator for the type of the variable is a stylistic one. It is valid because EvenIterator is a subtype of DataStructureIterator, so that every EvenIterator is also a DataStructureIterator.
As a rule of thumb, it is usually best for variables and method parameters to be typed as generally as possible, and for method return values to be typed as specifically as possible. That affords more flexibility to your code. How general or how specific "is possible" is a judgement call you must make, based on the nature of the code and how you intend for it to be used.
The reason you can use that interface is because EvenIterator is a DataStructureIterator. You should always use interfaces when creating a reference, as you don't usually need to know the specific implementation. Interfaces define a contract that implementing classes must conform to. Using interfaces helps to minimize coupling.
Using a simple example, an Animal (interface) can run (void run() method). Then, you want to have Dog and Cat classes and both of them can run, so you implement that interface. Now, you want to keep a list of animals that can run, so you should use Animal references instead of Dog or Cat, as all you need to know is that an Animal can run, not which kind of animal are you using.
Their example code is a bit sloppy. It would have been better as:
Iterator<Integer> iterator = this.new EvenIterator();
This makes it clear that the code using the Iterator only cares that it needs an Iterator (in this case of Integer). Experienced Java programmers often see code like that in the example and expect to find some specific reason for the code to need, in this case, DataStructureIterator. Usually the most general applicable type is clearer and makes less assumptions. For example, I habitually write:
List<V> list = new ArrayList<V>();
(Which I read as 'I need a list, it happens to be an ArrayList but that is irrelevant to the rest of the logic'.)
Joshua Bloch in his Effective Java book dedicates a whole item to this topic - "Refer to objects by their interfaces", and a part of it I would like to quote here:
If appropriate interface types exist, then parameters, return values, variables, and fields should all be declared using interface types.
...
If you get into the habit of using interfaces as types, your program will be much more flexible. If you decide that you want to switch implementations, all you have to do is change the class name in the constructor (or use a different static factory).

Instantiating object without knowing the concrete type

I am creating following java class.
class EntityCollection <E extends Entity, M extends Hashmap<?,E>> {
}
The idea is that the user of this class will tell me what type of objects to save in the collection and the actual store. So M can be simple Hashmap or LinkedHashmap.
I have two questions here:
How would I instantiate M inside my class? Is it possible?
AND
Is this a good approach or should I take some StoreFactory that would return me the store to use? Should I take that in the constructor of this class?
You can't do this the way you're set up due to type erasure. You can pull it off by having them pass the class to you.
Give this a read:
Create instance of generic type in Java?
Creating the hashmap is easy, you just pass the generic types through - or even use the diamond notation and have it done for you.
M m = new HashMap<>();
The complication is that you want to also be able to select the type of the Map. That can be done in a number of ways:
You could use the Factory pattern and pass in a factory object that creates the maps on demand.
You could generate the Map outside the class and pass it in on the constructor.
Have an abstract method to create the map. When creating an instance of the class people would implement that abstract method and generate the map for it.
For the second question there's no way to know without a lot more detail of what you are doing. That's an architectural decision and would most likely not fit into a stack overflow Q & A. This all seems a bit messy though, you are exposing a lot of the internal behavior of the classes. You would probably be better off thinking more about the behavior you want and the interface to provide that rather than the details of implementation.
For example you could have an enum { UNSORTED, INSERTION_ORDER, etc } and then instantiate the right Map based on that enum.

About the Java interface and polymorphism

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.

Java: How to create a collection of a specific parent type and not its subtypes?

I am learning Java for a test (tomorrow) and am wondering about a question that will probably never come up but has got me curious.
Is it possible to create a new collection class such as a list or something that can hold only a specific type and not its sub-types? Would I use generics to achieve this goal?
Not really, or at least not practically.
Subtypes should operate like sets in mathematical set theory. If B is a subset of A, any item in B is also an item in A.
In the same way, if B is a subtype of A, any item in B is also an item of A. Thus, any collection of A must be able to maintain items of B.
That being said, there may be convulted ways that B can override certain operations to explicitly break the ability to use it in a collection or to instantiate it.
I don't think generics will solve that problem.
If you create a custom collection class, you can check the class of the object on insert using reflection, and reject it if it's not of a particular exact type. Alternatively, if you have control over the class definition for the class contained in the collection, making it final will prevent subclasses from being created. (obviously this is a problem if you need subclasses for some other use)
The question is: why would you want that. If you have a list containing animals, why would you want to fill that list only with the "base animal", but prevent dogs or cats being added to the list. One of the basic concepts of OO is that you use an instance of a subclass everywhere where you need in instance of the base class (Wikipedia: Liskov substitution principle). If that does not apply in your situation, something might be wrong with your class hierarchy.
You could use "final" in the class definition of the contained class to disallow subtyping it. I don't immediately see how you can test for this or restrict your generics to require final classes. You can use reflection to test whether the class has the final modifier set, for instance when constructing the collection, and throw if it doesn't.
If the class itself is not final, you can check every single object added to the collection to ensure that its runtime class is exactly the class the collection wants and not a subclass of it.
see http://java.sun.com/docs/books/tutorial/reflect/ for info on reflection on Java.

Categories

Resources