科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件为什么说Java中继承是有害的(3)

为什么说Java中继承是有害的(3)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

这个代码成功编译,但是因为基类不知道关于stack指针堆栈的情况,这个stack对象当前在一个未定义的状态。下一个对于push()调用把新的项放入索引2的位置

作者:中国IT实验室 来源:中国IT实验室 2007年8月22日

关键字: java 继承

  • 评论
  • 分享微博
  • 分享邮件

  这个代码成功编译,但是因为基类不知道关于stack指针堆栈的情况,这个stack对象当前在一个未定义的状态。下一个对于push()调用把新的项放入索引2的位置。(stack_pointer的当前值),所以stack有效地有三个元素-下边两个是垃圾。(Java的stack类正是有这个问题,不要用它).
  对这个令人讨厌的继承的方法问题的解决办法是为Stack覆盖所有的ArrayList方法,那能够修改数组的状态,所以覆盖正确的操作Stack指针或者抛出一个例外。(removeRange()方法对于抛出一个例外一个好的候选方法)。
  这个方法有两个缺点。第一,如果你覆盖了所有的东西,这个基类应该真正的是一个interface,而不是一个class。如果你不用任何继承方法,在实现继承中就没有这一点。第二,更重要的是,你不能够让一个stack支持所有的ArrayList方法。例如,令人烦恼的removeRange()没有什么作用。唯一实现无用方法的合理的途径是使它抛出一个例外,因为它应该永远不被调用。这个方法有效的把编译错误成为运行错误。不好的方法是,如果方法只是不被定义,编译器会输出一个方法未找到的错误。如果方法存在,但是抛出一个例外,你只有在程序真正的运行时,你才能够发现调用错误。
  对于这个基类问题的一个更好的解决办法是封装数据结构代替用继承。这是新的和改进的Stack的版本:

 class Stack
{
private int stack_pointer = 0;
private ArrayList the_data = new ArrayList();

public void push( Object article )
{
the_data.add( stack_poniter++, article );
}

public Object pop()
{
return the_data.remove( --stack_pointer );
}

public void push_many( Object[] articles )
{
for( int i = 0; i < o.length; ++i )
push( articles[i] );
}
}

  到现在为止,一直都不错,但是考虑脆弱的基类问题,我们说你想要在stack创建一个变量, 用它在一段周期内跟踪最大的堆栈尺寸。一个可能的实现也许象下面这样:

 class Monitorable_stack extends Stack
{
private int high_water_mark = 0;
private int current_size;

public void push( Object article )
{
if( ++current_size > high_water_mark )
high_water_mark = current_size;
super.push( article );
}

publish Object pop()
{
--current_size;
return super.pop();
}

public int maximum_size_so_far()
{
return high_water_mark;
}
}

  这个新类运行的很好,至少是一段时间。不幸的是,这个代码发掘了一个事实,push_many()通过调用push()来运行。首先,这个细节看起来不是一个坏的选择。它简化了代码,并且你能够得到push()的派生类版本,甚至当Monitorable_stack通过Stack的参考来访问的时候,以至于high_water_mark能够正确的更新。

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章