0

Why is this a good practice to create objects using references in the upper level in inheritance hierarchy in object oriented programming, as I keep coming across this tendency in most professionally written codes.

e.g

List<Integer> list = new ArrayList<Integer>();
tural
  • 310
  • 4
  • 17
  • Interfaces define a common contract to which implementations are expected to adhere to without exposing the underlying implementation, this makes it flexible to the use the API with (generally) adversely constricting your choices (think arrays, `Vector` and `List`). Abstract classes reduce the amount of repeat work which is generally required just to get the interface up and running and generally focus on filling out those methods whose functionality is likely to be commonly re-used - in short - we're lazy and don't want keep writing the same code over and over again – MadProgrammer Sep 19 '15 at 03:22
  • Can you provide a snippet of code? Do you really mean references? – Thomas Andrews Sep 19 '15 at 03:22
  • Are you referring to the construct `List list = new ArrayList()`, meaning the use of the interface on the left, instead of the concrete class? – Andreas Sep 19 '15 at 03:25
  • the old `List list = new ArrayList()` question; of which the consensus opinion is wrong :) – ZhongYu Sep 19 '15 at 03:26
  • yes @Andreas , that's one exact example of my concern – tural Sep 19 '15 at 03:28
  • It's better to use the most specific type possible for a local variable. – ZhongYu Sep 19 '15 at 03:36
  • @bayou.io You have any reference for that statement. Both that there is a consensus (what is it?) and that it is wrong (says who and why?). – Andreas Sep 19 '15 at 03:36
  • @Andreas - the consensus is "program against interface", it's wrong because that adage applies to APIs, not implementations. This line of code is definitely implementation detail, and it's better to be as precise as possible. – ZhongYu Sep 19 '15 at 03:39
  • One reason I can think of is that it is shorter, e.g. the longest List implementation is called `CopyOnWriteArrayList`, so `List list = new CopyOnWriteArrayList()` is nicer than `CopyOnWriteArrayList list = new CopyOnWriteArrayList()`, if you don't need any concrete method that's not in the interface. – Andreas Sep 19 '15 at 03:40
  • 1
    @bayou.io So far that's your opinion stated there. I was asking if you had any references (links) to go with that. I'm not saying you're right or wrong, I'm just asking for references. – Andreas Sep 19 '15 at 03:41
  • @bayou.io I'm with Andreas, if you claim that "It's better to use the most specific type possible for a local variable" - the least you should do is provide some reasoning to go along with it (but references will be even better!). – Nir Alfasi Sep 19 '15 at 03:44
  • @Andreas - My opinion is not good enough? :) – ZhongYu Sep 19 '15 at 03:46
  • @alfasin - how about this answer - http://stackoverflow.com/a/3774026/2158288 – ZhongYu Sep 19 '15 at 03:51
  • @bayou.io that's a weak reasoning. Some of it is simply not true: "that its **performance** and semantic characteristics are manifest across all the code...". Do you also believe that it affects performance ? – Nir Alfasi Sep 19 '15 at 03:58
  • @alfasin - the performance characteristics of an ArrayList is more clear than a List. If a class implementation contains a list, and the implementer chose to use ArrayList, there must be a good reason for that; it's better to declare the instance variable as `ArrayList`, not just arbitrary `List` – ZhongYu Sep 19 '15 at 04:01
  • 1
    @alfasin It's very right on that point, actually. If you use `get(index)`, then it matter whether the list is an `ArrayList` or a `LinkedList`, because the performance is *very* different. If all you do is add and iterate, then it doesn't matter and using `List` is fine, but if you intend to use `get()`, you should declare it as `ArrayList` to say it matters. – Andreas Sep 19 '15 at 04:02
  • I respectfully disagree: hiding implementation details is one of the corner-stones of OO. You don't hide implementation detail only if you have a good reason not to do it - but it shouldn't be the default. By exposing which class you have chosen you will not be able to change it in the future without breaking client-code. As for that specific example you seem to have missed my point - performance *will* be the same regardless if you declare the reference as a `List` or as an `ArrayList`. – Nir Alfasi Sep 19 '15 at 04:06
  • 1
    @alfasin You missed 2 points: 1) It's arguing that specifying the concrete class allows the following code to *know* the characteristics of the implementation, such as performance (is using `get()` a good idea) and concurrency (it is safe to multi-thread). --- 2) It won't break client code, because this discussion is about the declaration of a *variable* and only affects the current method, not any clients, and is therefore not the same argument/context most used when discussing "program to interface". – Andreas Sep 19 '15 at 04:10
  • @tural Sorry for hijacking your question for this discussion. I hope the "duplicate" link I provided will help you find the answer you were looking for. – Andreas Sep 19 '15 at 04:15
  • Thanks @Andreas, yes, some of the answers gave me an idea in duplicate link. That was helpful – tural Sep 19 '15 at 04:17
  • @Andreas Based on what you guys decided that this code is only "local" and won't affect client code? I don't see any mentions to it in the question... The only good reasons I see to not using an interface are: 1. if such an interface doesn't exist. 2. If we need to use a method which is specific to an implementation of the interface. Even if we'll assume that the use is only "local" - then since you already know which implementation was chosen - you don't really have to specify it, right ? :) – Nir Alfasi Sep 19 '15 at 04:19
  • @alfasin Based on the fact that it's declaring a *variable*, not a return value, a parameter, or a field. – Andreas Sep 19 '15 at 04:21
  • Readers of the code will have a better understanding of what's going on with the implementation, if the code provides more detailed type information. Actually, that is the main point of static typing - it is for the benefit of the programmers to see which is what. (the other camp argues that variable names and contexts are enough to understand the code) – ZhongYu Sep 19 '15 at 04:22
  • @Andreas How can you tell that it will not be used as a return value ? – Nir Alfasi Sep 19 '15 at 04:22
  • @alfasin The value could, for sure, but the *return type* may be different from the *variable type*, and we're discussing the variable here. – Andreas Sep 19 '15 at 04:24
  • @Andreas sorry but I didn't understand your last comment... – Nir Alfasi Sep 19 '15 at 04:25
  • @alfasin `List myMethod() { ArrayList list = new ArrayList(); /* code that uses list, knowing that get() is good to use */; return list; }` --- Implementation code is using explicit knowledge, returned value is using API, i.e. "programming to interface". --- Should variable `list` be `List` or `ArrayList`? Arguments both ways depending on use *within* method. Client not affected either way. – Andreas Sep 19 '15 at 04:28
  • 1
    @tural - In practice, this is not a big deal either way -- don't argue with your colleague in real life :) – ZhongYu Sep 19 '15 at 04:31
  • @Andreas oh now I see what you meant. In that case I don't see any added value for one approach vs. the other. – Nir Alfasi Sep 19 '15 at 04:32
  • @bayou.io Although I ended up arguing the point you made early on, I'll stick with my early comment of using interface for conciseness (not lazyness, oh no), unless having a overriding reason not to. ;-) – Andreas Sep 19 '15 at 04:40
  • Yeah, better to develop *good* habits, and break them only if there's a good reason to do so. – Nir Alfasi Sep 19 '15 at 04:43
  • @Andreas - So why List, but not Collection? For conciseness, or laziness? :) My own practice is to always use the bottom type, not any one of the super types (there could be many). This is easier to practice than choosing a proper supertype:) – ZhongYu Sep 19 '15 at 04:45

0 Answers0