Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the negative aspects of Java class Stack inheriting from Vector?

By extending class Vector, Java’s designers were able to create class Stack quickly. What are the negative aspects of this use of inheritance, particularly for class Stack?

Thanks a lot.

like image 800
eomeroff Avatar asked May 27 '10 15:05

eomeroff


4 Answers

Effective Java 2nd Edition, Item 16: Favor composition over inheritance:

Inheritance is appropriate only in circumstances where the subclass really is a subtype of the superclass. In other words, a class B should only extend a class A only if an "is-a" relationship exists between the two classes. If you are tempted to have a class B extend a class A, ask yourself this question: Is every B really an A? If you cannot truthfully answer yes to this question, B should not extend A. If the answer is no, it is often the case that B should contain a private instance of A and expose a smaller and simpler API; A is not an essential part of B, merely a detail of its implementation.

There are a number of obvious violations of this principle in the Java platform libraries. For example, a stack is not a vector, so Stack should not extend Vector. Similarly, a property list is not a hash table, so Properties should not extend Hashtable. In both cases, composition would have been preferrable.

The book goes in greater detail, and combined with Item 17: Design and document for inheritance or else prohibit it, advises against overuse and abuse of inheritance in your design.

Here's a simple example that shows the problem of Stack allowing un-Stack-like behavior:

    Stack<String> stack = new Stack<String>();
    stack.push("1");
    stack.push("2");
    stack.push("3");
    stack.insertElementAt("squeeze me in!", 1);
    while (!stack.isEmpty()) {
        System.out.println(stack.pop());
    }
    // prints "3", "2", "squeeze me in!", "1"

This is a gross violation of the stack abstract data type.

See also

  • Wikipedia/Stack (data structure)

    In computer science, a stack is a last in, first out (LIFO) abstract data type and data structure.

like image 155
polygenelubricants Avatar answered Oct 24 '22 01:10

polygenelubricants


One problem is that Stack is a class, not an interface. This diverges from the design of the collection framework, where your noun is typically represented as an interface (e.g., List, Tree, Set, etc.), and there are specific implementations (e.g., ArrayList, LinkedList). If Java could avoid backward compatibility, then a more proper design would be to have a Stack interface, then VectorStack as an implementation.

A second problem is that Stack is now bound to Vector, which is generally avoided in favour of ArrayLists and the like.

A third problem is that you cannot easily provide your own stack implementation, and that stacks support very non-stack operations like getting an element from a specific index, including the potential for index exceptions. As a user, you may also have to know if the top of the stack is at index 0 or at index n. The interface also exposes implementation details such as capacity.

Of all the decisions in the original Java class library, I consider this one of the more peculiar ones. I doubt that Aggregation would have been much more expensive than inheritance.

like image 36
Uri Avatar answered Oct 24 '22 02:10

Uri


Having Stack subclass Vector exposes methods that are not appropriate for a stack, because a stack is not a vector (it violates the Liskov Substitution Principle).

For example, a stack is a LIFO data structure yet using this implementation you can call the elementAt or get methods to retrieve an element at a specified index. Or you can use insertElementAt to subvert the stack contract.

I think Joshua Bloch has gone on record as saying that having Stack subclass Vector was a mistake, but unfortunately I can't find the reference.

like image 6
John Topley Avatar answered Oct 24 '22 01:10

John Topley


Well, Stack should be an interface.

The Stack interface should define the operations a stack can perform. Then there could be different implementations of Stack that perform differently in different situations.

But, since Stack is a concrete class, this cannot happen. We are limited to one implementation of a stack.

like image 3
jjnguy Avatar answered Oct 24 '22 02:10

jjnguy