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();
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
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;
}
}