现在,我们来看一下另一个例子。假定一个Component代表一个GUI对象,比如按钮或者文本框之类的。请认真阅读下面的代码:
abstract class Component {
boolean isVisible;
int posXInContainer;
int posYInContainer;
int width;
int height;
abstract void paint(Graphics graphics);
void setWidth(int newWidth) {
void setHeight(int newHeight) {
class Button extends Component {
ActionListener listeners[];
void paint(Graphics graphics) {
class Container {
Component components[];
void add(Component component) {
假定你现在要写一个时钟clock组件。它是一个有时分针在转动的圆形的钟,每次更新时针跟分针的位置来显示当前的时间。因为这也是一个GUI组件,所以我们同样让它继承自Component类:
class ClockComponent extends Component {
void paint(Graphics graphics) {
//根据时间绘制当前的钟表图形
现在我们有一个问题了:这个组件应该是个圆形的,但是它现在却继承了Component的width跟height属性,也继承了setWidth 和 setHeight这些方法。
而这些东西对一个圆形的东西是没有意义的。
当我们让一个类继承另一个类时,我们需要再三的想想:它们之间是否有继承关系?ClockComponent是一个Component吗?它跟其他的Compoent(比如Button)是一样的吗?
跟ParticipantsInDB的那个案例相反的是,我们不得不承认ClockComponent确实也是一个Component,否则它就不能像其他的组件那样放在一个Container中。
因此,我们只能让它继承Component类(而不是用“代理”)。
它既要继承Component,又不要width, height, setWidth 和 setHeight这些,我们只好将这四样东西从Component里面拿走。而事实上,它也应该拿走。
因为已经证明了,并不是所有的组件都需要这四样东西(至少ClockComponent不需要)。如果一个父类描述的东西不是所有的子类共有的,那这个父类的设计肯定不是一个好的设计。我们有充分的理由将这些移走。
只是,如果我们从Component移走了这四样东西,那原来的那些类,比如Button就没了这四样东西,而它确实又需要这些的(我们假定按钮是方形的)。
一个可行的方案是,创建一个RectangularComponent类,里面有width,height,setWidth和setHeight这四样。然后让Button继承自这个类:
abstract class Component {
boolean isVisible;
int posXInContainer;
int posYInContainer;
abstract void paint(Graphics graphics);
abstract class RectangularComponent extends Component {
int width;
int height;
void setWidth(int newWidth) {
void setHeight(int newHeight) {
class Button extends RectangularComponent {
ActionListener listeners[];
void paint(Graphics graphics) {
class ClockComponent extends Component {
void paint(Graphics graphics) {
//根据时间绘制当前的钟表图形
这并不是唯一可行的方法。
另一个可行的方法是,创建一个RectangularDimension,这个类持有这四个功能,然后让Button去代理这个类:
abstract class Component {
boolean isVisible;
int posXInContainer;
int posYInContainer;
abstract void paint(Graphics graphics);
class RectangularDimension {
int width;
int height;
void setWidth(int newWidth) {
void setHeight(int newHeight) {
class Button extends Component {
ActionListener listeners[];
RectangularDimension dim;
void paint(Graphics graphics) {
void setWidth(int newWidth) {
dim。setWidth(newWidth);
void setHeight(int newHeight) {
dim。
setHeight(newHeight);
class ClockComponent extends Component {
void paint(Graphics graphics) {
//根据时间绘制当前的钟表图形
总结
当我们想要让一个类继承自另一个类时,我们一定要再三的检查:子类会不会继承了一些它不需要的功能(属性或者方法)?如果是的话,我们就得认真再想想:它们之间有没有真正的继承关系?如果没有的话,就用代理。
如果有的话,将这些不用的功能从基类转移到另外一个合适的地方去。