0

Examining the best practices in Java, we find avoiding inheritance is a good one. One of the reasons maybe illustrated in the following problem:

Here we have a sub-class "Stack" extends "ArrayList"

class Stack extends ArrayList
{   private int stack_pointer = 0;
    public void push( Object article )
    {   add( stack_pointer++, article );
    }
    public Object pop()
    {   return remove( --stack_pointer );
    }
    public void push_many( Object[] articles )
    {   for( int i = 0; i < articles.length; ++i )
            push( articles[i] );
    }
}

Let us say we are into adding to a stack using push() defined in the previous code, and then we want to clear the stack using clear() of the base-class -i.e ArrayList-

Stack a_stack = new Stack();
a_stack.push("1");
a_stack.push("2");
a_stack.clear();
  • Here the problem is

The code successfully compiles, but since the base class doesn't know anything about the stack pointer, the Stack object is now in an undefined state. The next call to push() puts the new item at index 2 (the stack_pointer's current value), so the stack effectively has three elements on it—the bottom two are garbage.

So my questions would be, why

base class doesn't know anything about the stack pointer

in other words, where is the state of the stack pointer being reserved?

source: Why extends is evil

Profess Physics
  • 317
  • 4
  • 11
  • For your idea, you have to implement the top of the stack. Also, you need to add some additional items, for example architecture: LIFO, FIFO, etc – Vasyl Lyashkevych Jun 28 '17 at 01:13
  • *"The next call to push() puts the new item at index 2"* No, it causes an `IndexOutOfBoundsException`. – Andreas Jun 28 '17 at 01:14
  • *"where is the state of the stack pointer being reserved?"* With the object data, same as all the other data that `ArrayList` defines, it's just that `ArrayList` doesn't know about it, only `Stack` does. --- Anyway, your code is flawed, since there is no need for `stack_pointer`, as the list size is the same thing. If you want to use `ArrayList`, then use it right. If you want your own `stack_pointer` (should be named `stackPointer`), then don't use `ArrayList`. – Andreas Jun 28 '17 at 01:16
  • Mr. @Andreas I was thinking of something else. However, what do you mean by "it causes an IndexOutOfBoundsException", I do guess it has nothing to do with that, It's just a matter of the updated stack_pointer variable where clear() in this case does not return it back to 0. – Profess Physics Jun 28 '17 at 01:25
  • 1
    Javadoc of [`add(int index, E element)`](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-int-E-) says: *"Throws `IndexOutOfBoundsException` if the index is out of range (index < 0 || index > size())"*. Since index is 2 and size is 0, you get ... **`IndexOutOfBoundsException`**. – Andreas Jun 28 '17 at 01:27
  • You are totally right. thx. man I forgot we are using add. not normal psuh() method – Profess Physics Jun 28 '17 at 01:28

2 Answers2

3

The variable stack_pointer is a member of the Stack class so how could the ArrayList superclass have any idea about it? Since it can't and doesn't the call to clear() isn't going to do anything to it.

You need to Override the clear() method in your Stack class.

Something like

@Override
public void clear()
{
   super.clear();
   stack_pointer = 0;
}

Then when a user calls clear() on a Stack it will cause the pointer to be reset.

Also you need to be aware that a user can call the functions add(), insert() etc on the Stack which since they aren't overridden will call the ArrayList functions. This is likely not what you want.

A better approach would be to create a Stack with an ArrayList inside so you can hide the methods you need to hide.

Something like

public class Stack
{
    private ArrayList<Object> stack = new ArrayList<Object>();
    private int stack_pointer;

    public void push(Object obj)
    {
       stack.add(stack_pointer++, obj);
    }

    // Other methods

    public void clear()
    {
       stack.clear();
       stack_pointer = 0;
    }
}
twain249
  • 5,666
  • 1
  • 21
  • 26
0

Here is one of the ways:

import java.util.ArrayList;

class Stack extends ArrayList {

    private int stack_pointer = 0;
    private int stack_mem = 16;
    private ArrayList<Object> mem = new ArrayList<Object>();

    public void push(Object article) {
        if (stack_pointer < stack_mem) {
            mem.add(article);
            stack_pointer++;
        }
    }

    public Object pop() {
        if (stack_pointer > 0) {
            return mem.remove(stack_pointer--);
        }
        return null;
    }

    public void clear() {
        stack_pointer = 0;
        mem.clear();
    }
}
Vasyl Lyashkevych
  • 1,920
  • 2
  • 23
  • 38