为什么Java中继承是有害的二
2008-01-05 20:05:10 来源:WEB开发网核心提示:有一天,有人也许运行这个代码并且注重到Stack没有运行的如想象的那么快,为什么Java中继承是有害的二,并且能够在重负荷下使用,你能够重写Stack,(例如,Monitorable_Stack.push(…)(在41行)不得不调用在Simple_stack等价的方法).程序员埋怨写所有这些行,以至于它不用ArrayL
有一天,有人也许运行这个代码并且注重到Stack没有运行的如想象的那么快,并且能够在重负荷下使用。你能够重写Stack,以至于它不用ArrayList并且继续提高Stack的效率。
这是新的倾向的和有意义的版本:
class Stack
{
PRivate int stack_pointer = -1;
private Object[] stack = new Object[1000];
public void push( Object article )
{
assert stack_pointer < stack.length;
stack[ ++stack_pointer ] = article;
}
public Object pop()
{
assert stack_pointer >= 0;
return stack[ stack_pointer-- ];
}
public void push_many( Object[] articles )
{
assert ( stack_pointer + articles.length )
注重到push_many不再多次调用push()—它做块传输。新的Stack运行正常;事实上,比前一个版本更好。不幸的是,派生类Monitorable_stack不再运行,因为假如push_many()被调用,它不正确的跟踪堆栈的使用(push()的派生类版本不再通过继续的push_many()方法调用,所以push_many()不再更新high_water_mark)。Stack是一个脆弱的类。与关闭它一样,事实上不可能通过小心来消灭这些类型的错误。
注重假如你用接口继续,你就没有这个问题,因为你没有继续对你有害的函数。假如Stack是接口,由Simple_stack和Monitorable_stack实现,那么代码就是更加健壮的。
我提供了一个基于接口的方法在Listing 0.1。这个解决方法和继续实现的方法一样的灵活:你能够用Stack抽象术语来写代码而不必担心你事实上在操作那种具体的堆栈。因为两个实现必须提供公共接口的所有东西,它很难使事情变糟。我仍然有和写基类的代码一样的只写一次,因为我用封装而不是继续。在底层,我不得不通过封装类中的琐碎的访问器方法来访问缺省的实现。(例如,Monitorable_Stack.push(…)(在41行)不得不调用在Simple_stack等价的方法).程序员埋怨写所有这些行,但是写这非凡行代码同消除重要的潜在bug是非常小的成本。
Listing 0.1. 用接口消除脆弱基类
1 import java.util.*;
2
3 interface Stack
4 {
5 void push( Object o );
6 Object pop();
7 void push_many( Object[] source );
8 }
9
10 class Simple_stack implements Stack
11 { private int stack_pointer = -1;
12 private Object[] stack = new Object[1000];
13
14 public void push( Object o )
15 { assert stack_pointer < stack.length;
16
17 stack[ ++stack_pointer ] = o;
18 }
19
20 public Object pop()
21 { assert stack_pointer >= 0;
22
23 return stack[ stack_pointer-- ];
24 }
25
26 public void push_many( Object[] source )
27 { assert (stack_pointer + source.length) < stack.length;
28
29 System.arraycopy(source,0,stack,stack_pointer+1,
source.length);
30 stack_pointer += source.length;
31 }
32 }
33
34
35 class Monitorable_Stack implements Stack
class Stack
{
PRivate int stack_pointer = -1;
private Object[] stack = new Object[1000];
public void push( Object article )
{
assert stack_pointer < stack.length;
stack[ ++stack_pointer ] = article;
}
public Object pop()
{
assert stack_pointer >= 0;
return stack[ stack_pointer-- ];
}
public void push_many( Object[] articles )
{
assert ( stack_pointer + articles.length )
注重到push_many不再多次调用push()—它做块传输。新的Stack运行正常;事实上,比前一个版本更好。不幸的是,派生类Monitorable_stack不再运行,因为假如push_many()被调用,它不正确的跟踪堆栈的使用(push()的派生类版本不再通过继续的push_many()方法调用,所以push_many()不再更新high_water_mark)。Stack是一个脆弱的类。与关闭它一样,事实上不可能通过小心来消灭这些类型的错误。
注重假如你用接口继续,你就没有这个问题,因为你没有继续对你有害的函数。假如Stack是接口,由Simple_stack和Monitorable_stack实现,那么代码就是更加健壮的。
我提供了一个基于接口的方法在Listing 0.1。这个解决方法和继续实现的方法一样的灵活:你能够用Stack抽象术语来写代码而不必担心你事实上在操作那种具体的堆栈。因为两个实现必须提供公共接口的所有东西,它很难使事情变糟。我仍然有和写基类的代码一样的只写一次,因为我用封装而不是继续。在底层,我不得不通过封装类中的琐碎的访问器方法来访问缺省的实现。(例如,Monitorable_Stack.push(…)(在41行)不得不调用在Simple_stack等价的方法).程序员埋怨写所有这些行,但是写这非凡行代码同消除重要的潜在bug是非常小的成本。
Listing 0.1. 用接口消除脆弱基类
1 import java.util.*;
2
3 interface Stack
4 {
5 void push( Object o );
6 Object pop();
7 void push_many( Object[] source );
8 }
9
10 class Simple_stack implements Stack
11 { private int stack_pointer = -1;
12 private Object[] stack = new Object[1000];
13
14 public void push( Object o )
15 { assert stack_pointer < stack.length;
16
17 stack[ ++stack_pointer ] = o;
18 }
19
20 public Object pop()
21 { assert stack_pointer >= 0;
22
23 return stack[ stack_pointer-- ];
24 }
25
26 public void push_many( Object[] source )
27 { assert (stack_pointer + source.length) < stack.length;
28
29 System.arraycopy(source,0,stack,stack_pointer+1,
source.length);
30 stack_pointer += source.length;
31 }
32 }
33
34
35 class Monitorable_Stack implements Stack
更多精彩
赞助商链接