A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

需求:创建一个Animal父类,分别创建Bird子类和Dog子类分别继承Animal父类,并且复用Animal的方法和定义自己独有的方法。
第一种:使用继承实现,代码如下:
  1. class Animal
  2. {
  3.         private void beat()
  4.         {
  5.                 System.out.println("心脏跳动...");
  6.         }
  7.         public void breath()
  8.         {
  9.                 beat();
  10.                 System.out.println("呼吸中...");
  11.         }
  12. }
  13. //继承Animal类,直接复用Animal的breath()方法
  14. class Bird extends Animal
  15. {
  16.         public void fly()
  17.         {
  18.                 System.out.println("我在飞翔....");
  19.         }
  20. }
  21. //继承Animal类,直接复用Animal的breath()方法
  22. class Dog extends Animal
  23. {
  24.         public void run()
  25.         {
  26.                 System.out.println("我在地上跑....");
  27.         }
  28. }
  29. class TestInherit
  30. {
  31.         public static void main(String[] args)
  32.         {
  33.                 Bird b = new Bird();
  34.                 b.breath();
  35.                 b.fly();
  36.                 Dog d = new Dog();
  37.                 d.breath();
  38.                 d.run();
  39.         }
  40. }
复制代码
第二种,使用组合关系实现,代码如下:
  1. class Animal
  2. {
  3.                 private void beat()
  4.         {
  5.                 System.out.println("心脏跳动...");
  6.         }
  7.         public void breath()
  8.         {
  9.                 beat();
  10.                 System.out.println("呼吸中...");
  11.         }
  12. }
  13. class Bird
  14. {
  15.         //将原来的父类嵌入原来的子类,作为子类的一个组合成分
  16.         private Animal a;
  17.         public Bird(Animal a)
  18.         {
  19.                 this.a = a;
  20.         }
  21.         //重新定义一个自己的breath()方法
  22.         public void breath()
  23.         {
  24.                 //直接复用Animal提供的breath()方法来实现Bird的breath()方法
  25.                 a.breath();
  26.         }
  27.         public void fly()
  28.         {
  29.                 System.out.println("我在飞...");
  30.         }
  31. }
  32. class Dog
  33. {
  34.         //将原来的父类嵌入原来的子类,作为子类的一个组合成分
  35.         private Animal a;
  36.         public Dog(Animal a)
  37.         {
  38.                 this.a = a;
  39.         }
  40.         //重新定义一个自己的breath()方法
  41.         public void breath()
  42.         {
  43.                 //直接复用Animal提供的breath()方法来实现Bird的breath()方法
  44.                 a.breath();
  45.         }
  46.         public void run()
  47.         {
  48.                 System.out.println("我在地上跑...");
  49.         }
  50. }
  51. class  TestComposite
  52. {
  53.         public static void main(String[] args)
  54.         {
  55.                 //显示创建被嵌入对象
  56.                 Animal a1 = new Animal();
  57.                 Bird b = new Bird(a1);
  58.                 b.breath();
  59.                 b.fly();
  60.                 //显示创建被嵌入对象
  61.                 Animal a2 = new Animal();
  62.                 Dog d = new Dog(a2);
  63.                 d.breath();
  64.                 d.run();
  65.         }
  66. }
复制代码
说明:两道程序运行结果相同。
问题:使用组合来实现复用时,需要创建两个Animal对象,是不是意味着使用组合关系时系统的开销会更大?
          组合关系的实现原理是什么?我们在开发时,确定使用继承还是使用组合,需要考虑哪些方面?

点评

鼓励鼓励  发表于 2013-3-10 07:44

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

3 个回复

倒序浏览
回答一:当然了,你第一个程序在内存中只要开辟两个对象的内存空间,而使用继承的时候,新开辟了两个一模一样的对象,你不觉得浪费吗?
回答二:组合技术通常用于你想要的在新类中使用现有类的功能而非它的接口的情形。即,你在新类中嵌入某个对象,借其实现你所需要的功能,但新类的用户看到的只是你为新类所定义的接口,而非嵌入对象的接口。为取得此效果,你需要在新类中嵌入一个private的现有类的对象。
         尽管在java语言中中,继承是非常重要的,但并不是要求我们一味的去使用它,相反,当你在适当的场合感觉到这种方法有效时,你就可以使用它。判断你到底是该用组合还是继承的最清晰的方法,就是问一看一下自己是否需要从新类向基类向上转型,如果你必须向上转型,那么继承是必要的,但如果你不需要,则应当考虑一下是否需要继承。 希望可以帮到你。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
张宁 发表于 2013-3-9 15:15
回答一:当然了,你第一个程序在内存中只要开辟两个对象的内存空间,而使用继承的时候,新开辟了两个一模一 ...

我个人以为系统开销不会变大啊,使用继承时,创建子类对象时,会隐式地创建父类对象,使用组合时,只不过是显示的创建了两个父类的对象,系统开销还是一样的,你觉得呢?
回复 使用道具 举报
问题一:感觉使用组合来实现复用时,需要创建两个类,所以更加消耗资源是肯定的
子类继承父类,尽管调用父类的构造函数,但是并没有真正在对内存开辟空间,创建父类,
所以感觉搂主的分析是对的,肯定是更加消耗资源。
问题二:其实你说的使用组合来实现复用,有一个更加专业的名词,叫作装饰模式,是25个设计模式当中的一种(当然单例模式也是其中一种)
那么问题可以转变为,继承和装饰模式的区别。
首先装饰模式的优点是
装饰模式可以在不创造更多的子类的模式下,将对象的功能加以扩展。并且是该扩展是动态的,也就是说,需要扩展哪个功能,就可以调用哪个。
在类中直接定义函数,是死的。无法动态的改变
如果使用过多的继承会增加系统的复杂性和偶合性。
所以如果你想在一个类中扩展功能,但是又不想把功能定死,就可以使用装饰模式。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马