0

检查 Java 中的最佳实践,我们发现避免继承是一个很好的做法。原因之一可能在以下问题中得到说明:

这里我们有一个子类“Stack”扩展了“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] );
    }
}

假设我们要使用push()前面代码中定义的方法添加到堆栈中,然后我们要使用clear()基类 - 即 ArrayList-来清除堆栈

Stack a_stack = new Stack();
a_stack.push("1");
a_stack.push("2");
a_stack.clear();
  • 这里的问题是

代码成功编译,但由于基类不知道堆栈指针的任何信息,因此 Stack 对象现在处于未定义状态。对 push() 的下一次调用将新项目放在索引 2 处(stack_pointer 的当前值),因此堆栈实际上包含三个元素 - 底部的两个是垃圾。

所以我的问题是,为什么

基类对堆栈指针一无所知

换句话说,堆栈指针的状态在哪里被保留?

来源:为什么扩展是邪恶的

4

2 回答 2

3

变量stack_pointer是类的成员,Stack那么超类怎么可能ArrayList知道呢?因为它不能也不会调用 toclear()不会对它做任何事情。

您需要重写类中的clear()方法Stack

就像是

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

然后,当用户调用clear()aStack时,它会导致指针被重置。

您还需要注意,用户可以调用函数add()insert()Stack因为它们没有被覆盖,所以会调用ArrayList函数。这可能不是您想要的。

更好的方法是创建一个Stack带有ArrayList内部的方法,这样您就可以隐藏需要隐藏的方法。

就像是

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;
    }
}
于 2017-06-28T01:15:59.390 回答
0

这是其中一种方法:

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();
    }
}
于 2017-06-28T01:25:35.083 回答