组合和继承是一样的吗? 如果我想实现组合模式,我如何在Java中做到这一点?
当前回答
不,两者都不一样。组合遵循“HAS-A”关系,继承遵循“IS-A”关系。组合的最佳例子是战略模式。
其他回答
它们完全不同。继承是一种“是-是”关系。作文是“has-a”。
通过使用另一个类C的实例作为类的字段来进行组合,而不是扩展C。java.util就是一个很好的例子,其中组合比继承要好得多。堆栈,它目前扩展了java.util.Vector。现在看来,这是一个大错。堆栈“is-NOT-a”向量;不应该允许任意插入和删除元素。应该是合成。
不幸的是,现在纠正这个设计错误已经太晚了,因为现在更改继承层次结构将破坏与现有代码的兼容性。如果Stack使用组合而不是继承,那么它总是可以被修改为使用另一种数据结构,而不会违反API。
我强烈推荐Josh Bloch的《Effective Java第二版》
项目16:比起继承,更喜欢组合 项目17:设计和文件的继承或禁止
好的面向对象设计不是随意扩展现有的类。你的第一直觉应该是作曲。
参见:
组合与继承:两种基本的类关联方法的比较
复合意味着创建一个与特定类有关系的类的对象。 假设学生与会计有关系;
继承是,这是带有扩展特性的前一个类。这意味着这个新类是具有一些扩展特性的旧类。 假设学生是学生,但所有的学生都是人。所以这是学生和人类之间的关系。这就是继承。
另一个例子,考虑一个汽车类,这将是一个很好的组合使用,一个汽车将“有”一个发动机,一个变速器,轮胎,座位,等等。它不会扩展任何这些类。
组合和继承是一样的吗?
它们不一样。
组合:它允许以对象的单个实例的方式处理一组对象。组合的目的是将对象“组合”成树状结构,以表示部分-整体层次结构
继承:类从其所有超类继承字段和方法,无论是直接的还是间接的。子类可以覆盖它继承的方法,也可以隐藏它继承的字段或方法。
如果我想实现组合模式,我如何在Java中做到这一点?
维基百科的文章足以在java中实现复合模式。
主要参与者:
组件:
是所有组件的抽象,包括复合组件吗 声明组合中对象的接口
叶:
表示组合中的叶对象 实现所有组件方法
复合材料:
表示一个复合组件(有子组件) 实现操作子节点的方法 实现所有Component方法,通常是将它们委托给其子方法
理解Composite模式的代码示例:
import java.util.List;
import java.util.ArrayList;
interface Part{
public double getPrice();
public String getName();
}
class Engine implements Part{
String name;
double price;
public Engine(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Trunk implements Part{
String name;
double price;
public Trunk(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Body implements Part{
String name;
double price;
public Body(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Car implements Part{
List<Part> parts;
String name;
public Car(String name){
this.name = name;
parts = new ArrayList<Part>();
}
public void addPart(Part part){
parts.add(part);
}
public String getName(){
return name;
}
public String getPartNames(){
StringBuilder sb = new StringBuilder();
for ( Part part: parts){
sb.append(part.getName()).append(" ");
}
return sb.toString();
}
public double getPrice(){
double price = 0;
for ( Part part: parts){
price += part.getPrice();
}
return price;
}
}
public class CompositeDemo{
public static void main(String args[]){
Part engine = new Engine("DiselEngine",15000);
Part trunk = new Trunk("Trunk",10000);
Part body = new Body("Body",12000);
Car car = new Car("Innova");
car.addPart(engine);
car.addPart(trunk);
car.addPart(body);
double price = car.getPrice();
System.out.println("Car name:"+car.getName());
System.out.println("Car parts:"+car.getPartNames());
System.out.println("Car price:"+car.getPrice());
}
}
输出:
Car name:Innova
Car parts:DiselEngine Trunk Body
Car price:37000.0
解释:
Part是一片叶子 汽车包含许多部件 汽车的不同部分已经添加到car中 汽车价格=(各部件价格)之和
关于组合和继承的利弊,请参考下面的问题。
喜欢组合而不是继承?
在简单的词聚合意味着有一个关系..
复合是聚合的一种特殊情况。在更具体的方式中,受限聚合称为组合。当一个对象包含另一个对象时,如果被包含的对象没有容器对象的存在就不能存在,那么它被称为组合。 示例:一个类包含学生。学生离不开课堂。课堂和学生之间存在着互动。
为什么使用聚合
代码的可重用性
当使用聚合时
当没有is关系时,代码重用也最好通过聚合来实现
继承
继承是一种父子关系继承意味着是一种关系
java中的继承是一种机制,在这种机制中,一个对象获得父对象的所有属性和行为。
在Java中使用继承 1代码可重用性。 2在子类中添加额外的特性以及方法覆盖(这样可以实现运行时多态性)。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap