Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we first declare subtypes as their supertype before we instantiate them?

Tags:

java

oop

Reading other people's code, I've seen a lot of:

List<E> ints = new ArrayList<E>();
Map<K, V> map = new HashMap<K, V>();

My question is: what is the point/advantage of instantiating them that way as opposed to:

ArrayList<E> ints = new ArrayList<E>();
HashMap<K, V> map = new HashMap<K, V>();

What also makes it odd is that I've never seen anything like:

CharSequence s = new String("String");

or

OutputStream out = new PrintStream(OutputStream);


Duplicates (of the first part of the question):

When/why to use/define an interface

Use interface or type for variable definition in java?

When should I use an interface in java?

why are interfaces created instead of their implementations for every class

What's the difference between these two java variable declarations?

like image 530
chrisdotcode Avatar asked Jan 06 '12 16:01

chrisdotcode


People also ask

What is subtype and supertype in Java?

A supertype is a generic entity type that has a relationship with one or more subtypes. A subtype is a sub-grouping of the entities in an entity type that is meaningful to the organization and that shares common attributes or relationships distinct from other subgroups.

What is a supertype in programming?

A supertype can have one or more subtypes, and a subtype can have one or more supertypes. A supertype can be a subtype of some other supertype, and a subtype can be a supertype of some other subtype. The relationship between a supertype and any of its subtypes involves the notion of substitutability.

What is subtyping in OOP?

Subtyping is a method for substitution and code reuse used in object-oriented programming languages to prevent unnecessary copying of largely similar code and promote code readability and prevent bugs.


3 Answers

Quick answer? Using interfaces and superclasses increases the portability and maintainability of your code, principally by hiding implementation detail. Take the following hypothetical example:

class Account {
    private Collection<Transaction> transactions;

    public Account() {
        super();
        transactions = new ArrayList<Transaction>(4);
    }

    public Collection<Transaction> getTransactions() {
        return transactions;
    }
}

I've declared a contract for an Account that states that the transactions posted to the account can be retrieved as a Collection. The callers of my code don't have to care what kind of collection my method actually returns, and shouldn't. And that frees me to change up the internal implementation if I need to, without impacting (aka breaking) unknown number of clients. So to wit, if I discover that I need to impose some kind of uniqueness on my transactions, I can change the implementation shown above from an ArrayList to a HashSet, with no negative impact on anyone using my class.

public Account() {
    super();
    transactions = new HashSet<Transaction>(4);
}

As far as your second question, I can say that you use the principal of portability and encapsulation wherever they make sense. There are not a terrible lot of CharSequence implementations out there, and String is by far the most used common. So you just won't see alot of developers declaring CharSequence variables in their code.

like image 193
Perception Avatar answered Oct 11 '22 00:10

Perception


Using interfaces has the main advantage that you can later change the implementation (the class) without the need to change more than the single line where you create the instance and do the assignment.

like image 20
Rostislav Matl Avatar answered Oct 10 '22 23:10

Rostislav Matl


For

List<E> ints = new ArrayList<E>();
Map<K, V> map = new HashMap<K, V>();

List and Map are the interfaces, so any class implementing those interfaces can be assigned to these references.

ArrayList is one of the several classes (another is LinkedList) which implement List interface.

Same with Map. HashMap, LinkedHashMap, TreeMap all implement Map.

It is a general principle To program for interfaces and not for implementations. Due to this, the programming task becomes easier. You can dynamically change the behavior of the references.

If you write

ArrayList<E> ints = new ArrayList<E>();
HashMap<K, V> map = new HashMap<K, V>();

ints and map will be ArrayList and HashMap only, forever.

like image 7
Bhushan Avatar answered Oct 11 '22 00:10

Bhushan