|  | 本文参考: 《Java面向对象编程》,作者:孙卫琴
 《漫画Java编程》,作者:孙卫琴,杜聚宾
 
 继承关系最大的弱点就是打破了封装。在设计对象模型时,每个类都应该封装它的属性以及实现细节,这样,当这个类的实现细节发生变化时,不会对其他依赖它的类造成影响。而在继承关系中,子类能够访问父类的属性和方法,也就是说,子类会访问父类的实现细节,子类与父类之间是紧密耦合关系,当父类的实现发生变化,子类的实现也不得不随之变化,这削弱了子类的独立性。
 
 由于继承关系会打破封装,这增加了维护软件的工作量。尤其是在一个Java软件系统还使用了一个第三方提供的Java类库的场合。例如在基于Web的Java应用中,曾经流行使用Apache开源软件组织提供的Struts框架,这个框架的一个扩展点为Action类,在Struts的低版本中,Action类有以下两个方法perform()和saveErrors():
 | public ActionForward perform( ActionMapping mapping,
 ActionForm form,
 ServletRequest request,
 ServletResponse response)throws Exception
 
 protected void saveErrors(HttpServletRequest request, ActionErrors errors)
 | 
 在Java应用中,可以创建继承Action类的子类,例如LoginAction,然后在LoginAction类中覆盖Action类的perform()方法,在perform()方法中则会调用saveErrors()方法:
 
 
 | public class LoginAction extends Action{ 
 public ActionForward perform(…){  //覆盖Action类的perform方法
 ActionErrors errors=new ActionErrors();
 ……
 saveErrors(request ,errors);  //调用Action类的saveErrors()方法
 }
 }
 | 
 而在Struts的升级版本中,Action类的perform()方法改名为execute()方法,并且saveErrors(HttpServletRequest request, ActionErrors errors)改为:
 
 
 | saveErrors(HttpServletRequest request, ActionMessages errors) | 
 假如现有的Java应用希望改为使用Struts的升级版本,就必须对自定义的所有Action子类进行修改:
 
 
 | public class LoginAction extends Action{ public ActionForward execute(…){  //把perform()方法改为execute()方法
 ActionMessages errors=new ActionMessages();  //把ActionErrors改为ActionMessages
 ……
 saveErrors(request ,errors);
 }
 }
 | 
 从以上例子可以看出,当由第三方提供的Struts框架的Action类做了修改,软件系统中所有Action的子类也要做相应地修改。
 由于继承关系会打破封装,还会导致父类的实现细节被子类恶意篡改的危险。例如以下Account类的withdraw()方法和save()方法分别用于取款和存款:
 
 
 | public class Account{ protected double balance;  //余额
 protected boolean isEnough(double money){
 return balance>=money;
 }
 public void withdraw(double money)throws Exception{  //取款
 if(isEnough(money)) balance-= money;
 else throw new Exception("余额不足!");
 }
 
 public void save(double money)throws Exception{  //存款
 balance+=money;
 }
 }
 | 
 它的子类SubAccount覆盖了Account类的isEnough()方法和save()方法的实现,使得该账户允许无限制的取款,并且按照实际存款数额的10倍来存款:
 
 
 | public class SubAccount extends Account{ protected boolean isEnough(double money){  //覆盖父类的isEnough()方法
 return true;
 }
 
 public void save(double money)throws Exception{  //覆盖父类的save()方法
 balance+=money*10;
 }
 }
 | 
 以下程序定义了Account类型的引用变量account,实际引用SubAccount实例,根据Java虚拟机的动态绑定规则,account.save()和account.withdraw()方法会和SubAccount实例的相应方法绑定:
 
 
 | Account account=new SubAccount(); account.withdraw(2000);  //调用SubAccount实例的withdraw()方法
 account.save(100);  //调用SubAccount实例的save()方法
 | 
 程序猿的技术大观园:www.javathinker.net
 
 
 
 [这个贴子最后由 admin 在 2022-03-15 14:47:23 重新编辑]
 | 网站系统异常 
 
 
    
     | 系统异常信息 |  
     | Request URL: 
http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=211 
 java.lang.NullPointerException
 
 如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员。
 |  |