类B具有类A的所有方法和属性,并且有所扩展,满足子类的所有便利条件,但是类A和类B在逻辑上并不具有直接的父子关系,甚至可能它们是逻辑上同一级别的两个类,只是类B比类A具有更多的特性而已。请举一个这样的case,好象不可理解。

解决方案 »

  1.   

    做第三个类,可以和A类雷同,然后A和B都继承它.我觉得如果两个类很相似的话,它们一定有关系,只是你还没有抽象出来.
      

  2.   

    《Java编程思想》一书中给我们的建议是:假如你不需要用到向上转型,就不要动用继承。
      

  3.   

    根据面向对象的里氏替换(LSP)原则:
    若对于每一个类型S的对象o1,都存在一个类型T的对象o2,使得在所有针对T编写的程序P中,用o1替换o2后,程序P的行为功能不变,则S是T的子类型。
    LSP原则清楚地指出,面向对象中Is-A关系是就行为功能而言。行为功能(behavior)不是内在的、私有的,而是外在、公开的,是客户程序所依赖的。行为功能(behavior)才是软件所关注的问题!所有派生类的行为功能必须和客户程序对其基类所期望的保持一致。
    --------------------------------------------------------------
    因此我不明白楼主: "逻辑上并不具有直接的父子关系",逻辑上是指什么意思,如果逻辑上是从行为功能
    而谈的,当然不能是继承关系,
    最好说明一下实际情况,同意 rower203(华仔) 的意见,最好说明一下实际case,才好分析
      

  4.   

    从各位的回答可以看出一个结论,尽量不要使用继承!是吗?
    TraBant(顶风),组合使用起来很累,如果类A有很多方法,类B中包含一个A的对象,则往往必须在类B中定义类A中的所有方法,而且一旦类A中的方法有所增减,就必须同时增减类B中的方法,同样造成了可维护性的降低。
    rower203(华仔),这样的case其实很多的,典型的比如人有id和name两个属性(特定情况下我们只需要人名即可),而商品有id、name和price三个属性。
    vssivl(克斯),你的方法有一定道理,只是若构建一个与类A雷同的类,类A和类B都去继承它,又会出现这样一个问题:如果无法找出类A和类B在逻辑上的父,那这个公共的父类在逻辑上仍旧是不合理的。比如上面所说的人和商品,它们逻辑上的父应该是什么呢?也许我分析能力还有所欠缺,有些相似的类无法找到它们之间特征上的联系。
    JackKen(小马过河),你知道为什么《TIJ》中这么说吗?相信这是在权衡了各方面代价之后得到的结论,那在类中存在大量方法(超过20个)时,这一点是否同样适用呢?我知道,如果一个类包含大量方法,则应该考虑该类是否承担了过多的工作,是否可以分拆该类,可事实上我已经无法拆分现在正在编写的这个类,因为它代表的就是一个可能存在很多动作的事物。
      

  5.   

    vssivl(克斯)的方法不错,一般都采这种方式来解决。当然也可以用组合!:)
      

  6.   

    benbendragon(笨笨龙),按照这个LSP原则,我的这个问题就得到了答案,那就是不能继承!
    那么,可维护性的降低、复杂性的增加和编写难度的提高这些问题如何处理?
      

  7.   

    不明白
    "组合使用起来很累,如果类A有很多方法,类B中包含一个A的对象,则往往必须在类B中定义类A中的所有方法,而且一旦类A中的方法有所增减,就必须同时增减类B中的方法,同样造成了可维护性的降低。"这句话是什么意思,B中声明一个A的对象,还需要"在类B中定义类A中的所有方法"?????????
      

  8.   

    B中声明一个A的对象,难道将这个A对象设成public直接给外部使用,现在是A和B具有很多相同的方法,而要通过组合使B具有A的所有方法,就必须在B中定义A中的所有方法,不是吗?
      

  9.   

    public class A{
      public void f1(){
        //
      }
    }public class B{
      private A a;
      public void f1(){
        a.f1();
      }
    }
      

  10.   

    根据"不要和陌生人说话"模式(<<UML和模式应用>>一书中提及),确实应该象你说的那样,可是书中也指出这是一个合理的建议,在一些特殊的情况下可以违背,针对你的情况"我已经无法拆分现在正在编写的这个类,因为它代表的就是一个可能存在很多动作的事物。",这个类是"代理"的情况,我认为可以
    B中声明一个A的对象,B中声明一个方法返回A的一个实例使用A的方法.当然更好的解决方法的问题是真的已经无法拆分这个类了吗??有没有可能使用设计模式中如状态模式等
      

  11.   

    能简要说说这个状态模式吗?
    在我现有的知识范畴内,我确实无法拆分这个类了,这是一些类似于java中File类的类,对某个事物有大量的操作,我数了一下java中的File类的方法,除去直接从Object继承的,共有39个之多!我现在写的还没这么多,可能类A中有20多个方法,类B中有30来个方法。我们是否不应该考虑编程的难度?
      

  12.   

    说说我这个类的结构吧:
    它本来就是一个组合而成的类,包含四个属性,三个HashMap对象和一个ArrayList对象,这四个属性用于表示该事物的四个特征,是必须的,对于这四个对象中的每一个都有增、删、查、改、清除的方法。另外有一些通过调用这些方法实现的特殊方法,以操作一些特殊的事物特征。
    可以拆分的方案是,将这四个对象抽出来,让外界可以获得这四个对象的句柄,然后直接操作这些对象。但是我记得,让外界直接修改内部对象是不可取的,因为你无法预料这些内部对象会被如何处理,它有可能会被赋值为null,而这往往是不允许的。
    你能否想到另外一种拆分方案?
      

  13.   

    人,商品:这并不是“类B具有类A的所有方法和属性,并且有所扩展”的case。人,商品那里有共同的方法?人能走路、说话,商品不能。如果把他们具有id,name共同的属性抽象出来也可以,暂且叫它为“物”,这样人可继承物,商品亦可继承物,这时它们是具有逻辑关系的。对于“类B具有类A的所有方法和属性,并且有所扩展”,我看是具有逻辑关系的。只是模型要建得合乎逻辑才是。
      

  14.   

    rower203(华仔),不是所有的“人”对象都要有走路,说话方法的,也许我只是将人名作为数据保存,那么这个“人”类可能只具有get/set方法,而商品也只有get/set方法,具体应用中的逻辑和日常生活中的逻辑不一定完全吻合的。
    也许我这个例子举得不是很好,你完全可以自己想到一些例子的。
      

  15.   

    突然明白了!事实上,对于相似的类,总是可以找到它们逻辑上共同的父,只是可能抽象程度更高而已,以前我是囿于一个特定的领域中了,其实只要超出这个特定领域,就能找到公共的父!另外,这个LSP原则确实很有启发,感谢两位,加分以报!