1

I recently read that I should use general classes instead of specific classes when proramming. I can't figure out why it is suggested.

example: Let's say that we have a class MyPanel that inherits from JPanel. MyPanel a non-inherited method called getLastChild.

instead of:

MyPanel panel = new MyPanel():
Component last = panel.getLastChild();

it is suggested to do this:

JPanel panel = new MyPanel();
Component last = ((MyPanel)panel).getLastChild();

I don't see why I should choose the second one.

sfabriece
  • 121
  • 2
  • 10
  • You should not. You misunderstood the advice or the advice was wrong. Or maybe you are omitting some important piece of code. – fdreger May 10 '14 at 20:25
  • 1
    See also See also Liskov Substitution Principal, ex. http://en.wikipedia.org/wiki/Liskov_substitution_principle. – jordan May 10 '14 at 20:26

4 Answers4

4

You are correct, this example indeed makes no sense.

The general rule of thumb is that you should use the most general class that still has the appropriate functionality. This way, you allow yourself the freedom to change the concrete class you're using and have the rest of the program continue working. For example, consider the JDK's Collections.sort(List). The same method call can be used with an ArrayList, a LinkedList, or any other List - it does not care about the specifics of how that list is implemented, just about the fact that it's a list.

Your example, however, is different. If you need to call MyPanel.getLastChild(), you most certainly care about having a MyPanel - you can't just use any other JPanel. Since you already have this dependency, it makes no sense declaring your variable as a JPanel and downcasting it just to call getLastChild().

Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • 2
    at last someone is making sense and noticing the cast. – fdreger May 10 '14 at 20:26
  • Thanks for the answer. I never really understood the whole concept. Your answer puts everything in context. Hence the reason to program against interfaces. – sfabriece May 11 '14 at 02:18
0

A good example would be:

List<Integer> list = new ArrayList<Integer>;

instead of

ArrayList<Integer> list = new ArrayList<Integer>;

Why?

tl;dr It gives you more flexibility and generalizes your code for free.

Explanation

Whenever you want to pass a list you will use List instead of ArrayList. For example you have a method:

public void doSomething(List<Integer> list)

Later you can change your implementation easily if you realize that for example LinkedList is a better choice.

Adam Stelmaszczyk
  • 19,665
  • 4
  • 70
  • 110
-1

That second one brings greater flexibility. If you declare panel to be of type MyPanel, then it can ONLY be MyPanel (or classes that inherit from MyPanel), whereas if you declare panel as type JPanel, it can be a generic JPanel OR any subclass of JPanel (including MyPanel). This makes your code more portable and easier to edit down the road. Your component might only be a MyPanel now, but what if that changes later?

Joshua Zollinger
  • 757
  • 1
  • 8
  • 17
-1

You can now develop utility method that operates with JPanels. Let's call it foo(JPanel p).

Now you can use it with any JPanel including MyPanel. But why? You can define the method as following: foo(MyPanel p) and use it with MyPanel until you develop second panel that it called OtherPanel. You cannot send this OtherPanel to foo() that operates with MyPanel only.

However the first (general) version of foo() can be used for both and for any other class that extends JPanel and developed by you, by me or by any other programmer.

I hope that this simple example is enough to understand the need of generalization.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • I'd be glad to know the reason of the serial downvoter. – AlexR May 10 '14 at 20:28
  • As fdreger noted above, it's because nearly everyone (myself included) missed part of the question and so didn't quite answer OP's question – awksp May 10 '14 at 20:31