组合和继承是一样的吗? 如果我想实现组合模式,我如何在Java中做到这一点?


当前回答

Though both Inheritance and Composition provides code reusablility, main difference between Composition and Inheritance in Java is that Composition allows reuse of code without extending it but for Inheritance you must extend the class for any reuse of code or functionality. Another difference which comes from this fact is that by using Composition you can reuse code for even final class which is not extensible but Inheritance cannot reuse code in such cases. Also by using Composition you can reuse code from many classes as they are declared as just a member variable, but with Inheritance you can reuse code form just one class because in Java you can only extend one class, because multiple Inheritance is not supported in Java. You can do this in C++ though because there one class can extend more than one class. BTW, You should always prefer Composition over Inheritance in Java, its not just me but even Joshua Bloch has suggested in his book

其他回答

复合意味着创建一个与特定类有关系的类的对象。 假设学生与会计有关系;

继承是,这是带有扩展特性的前一个类。这意味着这个新类是具有一些扩展特性的旧类。 假设学生是学生,但所有的学生都是人。所以这是学生和人类之间的关系。这就是继承。

它们完全不同。继承是一种“是-是”关系。作文是“has-a”。

通过使用另一个类C的实例作为类的字段来进行组合,而不是扩展C。java.util就是一个很好的例子,其中组合比继承要好得多。堆栈,它目前扩展了java.util.Vector。现在看来,这是一个大错。堆栈“is-NOT-a”向量;不应该允许任意插入和删除元素。应该是合成。

不幸的是,现在纠正这个设计错误已经太晚了,因为现在更改继承层次结构将破坏与现有代码的兼容性。如果Stack使用组合而不是继承,那么它总是可以被修改为使用另一种数据结构,而不会违反API。

我强烈推荐Josh Bloch的《Effective Java第二版》

项目16:比起继承,更喜欢组合 项目17:设计和文件的继承或禁止

好的面向对象设计不是随意扩展现有的类。你的第一直觉应该是作曲。


参见:

组合与继承:两种基本的类关联方法的比较

遗产怎么会是危险的?

让我们举个例子

public class X{    
   public void do(){    
   }    
}    
Public Class Y extends X{
   public void work(){    
       do();    
   }
}

1)正如上面的代码所示,类Y与类X具有很强的耦合性。如果超类X发生任何变化,Y可能会急剧断裂。假设在未来的类X中实现了一个具有以下签名的方法work

public int work(){
}

改变是在类X中完成的,但它将使类Y不可编译。所以这种依赖可以上升到任何程度,这是非常危险的。每次超类都可能对其所有子类中的代码没有完全可见性,子类可能会一直注意到在超类中发生了什么。因此,我们需要避免这种强而不必要的耦合。

合成如何解决这个问题?

让我们复习一下同样的例子

public class X{
    public void do(){
    }
}

Public Class Y{
    X x = new X();    
    public void work(){    
        x.do();
    }
}

这里我们在Y类中创建X类的引用,并通过创建X类的实例调用X类的方法。 现在所有的强耦合都消失了。父类和子类现在彼此高度独立。类可以自由地进行更改,这在继承情况下是危险的。

2)第二个非常好的优点是它提供了方法调用的灵活性,例如:

class X implements R
{}
class Y implements R
{}

public class Test{    
    R r;    
}

在测试类中使用r引用,我可以调用X类以及Y类的方法。这种灵活性在继承中是不存在的

3)另一个巨大优势:单元测试

public class X {
    public void do(){
    }
}

Public Class Y {
    X x = new X();    
    public void work(){    
        x.do();    
    }    
}

在上面的例子中,如果x实例的状态未知,可以用一些测试数据很容易地模拟出来,所有的方法都可以很容易地测试出来。这在继承中是完全不可能的,因为您严重依赖于超类来获取实例的状态并执行任何方法。

4)我们应该避免继承的另一个很好的理由是Java不支持多重继承。

让我们举个例子来理解这一点:

Public class Transaction {
    Banking b;
    public static void main(String a[])    
    {    
        b = new Deposit();    
        if(b.deposit()){    
            b = new Credit();
            c.credit();    
        }
    }
}

很高兴知道:

组合在运行时很容易实现,而继承在编译时提供其特性 组合也称为HAS-A关系,继承也称为is - a关系

因此,由于上述各种原因,要养成总是喜欢组合而不是继承的习惯。

继承Vs组合。

继承和组合都用于类行为的可重用性和扩展。

继承主要用在IS-A一类算法编程模型中,关系类型是指相似类型的对象。的例子。

吸尘器是一辆车 Safari是一辆车

这些是Car家族的。

Composition表示HAS-A关系类型。它显示了一个对象的能力,如Duster有五个齿轮,Safari有四个齿轮等。每当我们需要扩展现有类的能力时,就使用复合。例如,我们需要在Duster对象中添加一个齿轮,然后我们必须创建一个齿轮对象,并将其组合到Duster对象中。

除非所有派生类都需要这些功能,否则不应该对基类进行更改。对于这个场景,我们应该使用Composition。如

由类B派生

类A由类C派生

类A由类D派生。

当我们在类A中添加任何功能时,即使类C和类D不需要这些功能,它也可以用于所有子类。对于这个场景,我们需要为这些功能创建一个单独的类,并将其组合到所需的类中(这里是类B)。

下面是例子:

          // This is a base class
                 public abstract class Car
                    {
                       //Define prototype
                       public abstract void color();
                       public void Gear() {
                           Console.WriteLine("Car has a four Gear");
                       }
                    }


           // Here is the use of inheritence
           // This Desire class have four gears.
          //  But we need to add one more gear that is Neutral gear.

          public class Desire : Car
                   {
                       Neutral obj = null;
                       public Desire()
                       {
     // Here we are incorporating neutral gear(It is the use of composition). 
     // Now this class would have five gear. 

                           obj = new Neutral();
                           obj.NeutralGear();
                       }

                       public override void color()
                       {
                           Console.WriteLine("This is a white color car");
                       }

                   }


             // This Safari class have four gears and it is not required the neutral
             //  gear and hence we don't need to compose here.

                   public class Safari :Car{
                       public Safari()
                       { }

                       public override void color()
                       {
                           Console.WriteLine("This is a red color car");
                       }


                   }

   // This class represents the neutral gear and it would be used as a composition.

   public class Neutral {
                      public void NeutralGear() {
                           Console.WriteLine("This is a Neutral Gear");
                       }
                   }

构图是指某物由不同的部分组成,并且它与这些部分之间有很强的关系。如果主体死亡,其他部分也会死亡,他们就不能拥有自己的生命。一个粗略的例子就是人体。取出心脏,其他部分就会消失。

继承就是你取已经存在的东西并使用它。没有很强的关系。一个人可以继承他父亲的财产,但他也可以不继承。

我不知道Java,所以我不能提供一个例子,但我可以提供一个概念的解释。