现在的位置: 首页 > 综合 > 正文

黑马程序员—学习继承、聚合、组合

2013年01月30日 ⁄ 综合 ⁄ 共 3376字 ⁄ 字号 评论关闭

---------------------- android培训java培训、期待与您交流! ----------------------

第七天

继承

(1)提高代码的复用性。

(2)让类与类之间产生了关系。有了这个关系,才有了多态的特性。

注意:

千万不要为了获取其他类的功能,简化代码而继承。

必须是类与类之间有所属关系才能继承。所属关系 :is a;谁是谁中的一种。

Java语言中只支持单集成,不支持多继承。(即是说:一个类只能继承一个父类,不能继承多个父类。)因为多继承带来安全隐患:

当多个父类中定义了相同功能时,但功能内容不同时,子类对象不确定要运行哪一个。

class A

{

void show()

{

System.out.println("a");

}

}

class B

{

void show()

{

System.out.println("b");

}

}

class C extends A,B

{

C c=new C();

c.show();

}

子类对象c不确定要打印a还是b

Java中有多实现(C++中的多继承)

Java支持多层继承。就是B继承AC继承B

如何使用一个集成体系中的功能呢?

先查阅体系父类的描述,因为父类中定义的是该体系中的共性功能。

通过了解共性功能,就可以知道该体系的基本功能。

那么在具体调用时,要创建最子类的对象,为什么呢?

(1)因为有可能父类不能创建对象。

(2)创建子类对象可以使用更多的功能,包括基本的和特有的方法。

聚合:

组合:

聚合与组合的区别?

聚合:表示两个对象之间是整体和部分的关系,部分的生命周期可以超越整体。如电脑和鼠标,就可以用一下图形表示:



组合:表示两个对象之间是整体和部分的关系,部分的生命周期不能超越整体,或者说不能脱离整体而存在。组合关系的部分,是不能在整体之间进行共享的。如人和眼睛的关系:

不过,如果你要说,眼睛可以移植,是不是说可以脱离人而存在,它们就不是组合关系了?其实,UML中对象的关系都是在相应的软件环境或实际场景下定义的,这里区别聚合和组合的关系,关键还是在于它们之中整体和部分的关系强、弱,以及它们之间的依附关系。如果刚才说眼睛可以移植给别人,那你也可以把它认为是聚合,这都要结合实际场景来说明。

另外两个比较重要的关系是关联和依赖:
关联:简单的可以认为,如果一个类作为了另外一个类的属性,那一定是关联关系。但你要知道,聚合是一种特殊的关联,而组合又是一种特殊的聚合。一般的关联我们认为是平级的、无整体部分关系的,如朋友关系。

依赖:对象之间的临时关系,临时性体现在不超越方法的周期。简单的说,在方法使用到的,如参数类,就一定是依赖关系。

最后想说一句,实际工作中,我并没有发现区分这四种关系有多么大的用处,也许自己还没有碰到,只是觉得可能每个学习它的同学总想把它搞清楚,但实际工作中作用并不明显。

组合和聚合是有很大区别的,这个区别不是在形式上,而是在本质上:
比如A类中包含B类的一个引用b,当A类的一个对象消亡时,b这个引用所指向的对象也同时消亡(没有任何一个引用指向它,成了垃圾对象),这种情况叫做组合,反之b所指向的对象还会有另外的引用指向它,这种情况叫聚合。
在实际写代码时组合方式一般会这样写:
A类的构造方法里创建B类的对象,也就是说,当A类的一个对象产生时,B类的对象随之产生,当A类的这个对象消亡时,它所包含的B类的对象也随之消亡。
聚合方式则是这样:
A类的对象在创建时不会立即创建B类的对象,而是等待一个外界的对象传给它
传给它的这个对象不是A类创建的。
现实生活中:
人和人和手,脚是组合关系,因为当人死亡后人的手也就不复存在了。人和他的电脑是聚合关系。class Hand{

2 }

3 class Computer{

4 }

5 组合:

6 class Person{

7 private Hand hand;

8 public Person(){

9 hand = new Hand();

10 }

11 }

12 聚合:

13 class Person{

14 private Computer computer;

15 public setComputer(){

16 computer = new Computer();

17 }

18 }

子父类中变量的特点:

如果子类中出现非私有的同命成员变量时。

子类要访问本类中的变量,用this

子类要访问父类中的同命变量,用super

Super的使用和this基本一致。

子父类中函数的特点-----覆盖

当子类出现和父类一模一样的函数时,

当子类对象调用该函数时,会运行子类函数的内容。

如同父类函数被覆盖一样。

这就是函数的另一个特性-----重写(覆盖)。

当子类继承父类,但是子类虽然具备了父类的某个功能,但是该功能的内容却和父类的不一样,这时,就没有必要定义新功能,而使用覆盖,保留父类的功能定义,并重写功能内容。

class ExtendsDemo2 

{

public static void main(String[] args) 

{

Zi z=new Zi();

z.speak();

}

}

class Fu

{

void show()

{

System.out.println("fu show");

}

void speak()

{

System.out.println("vb");

}

}

class Zi

{

void speak()

{

System.out.println("java");

}

void show()

{

System.out.println("zi show");

}

}

结果:

java

注意:

(1)子类覆盖父类,必须保证子类的权限大于等于父类的权限,才能覆盖,否则编译失败。

(2)静态只能覆盖静态。

注意:

重载:只看同名函数的参数列表。

重写:子父类方法要一模一样。

子父类中构造函数的特点----子类实例化过程

class ExtendsDemo3 

{

public static void main(String[] args) 

{

Zi z=new Zi();

}

}

class Fu

{

Fu()//这是构造函数

{

System.out.println("fu run");

}

}

class Zi extends Fu

{

Zi()

{

//这里隐藏了super();

System.out.println("zi run");

}

}

结果:

fu run

zi run

在对子类对象进行初始化时,父类的构造函数也会运行。

那是因为子类的构造函数默认第一行有一条隐式的语句 super();

super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是 super()。

为什么子类一定要访问父类中的构造函数。

因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。

所以子类在对象初始化时,要先访问一下父类中的构造函数。

如果要访问父类中指定的构造函数,可以通过手动定义super语句方式来指定。

注意:super语句一定定义在子类构造函数的第一行。

结论:

子类中的所有的构造函数,默认都会访问父类中空参数的构造函数。

因为子类每一个构造函数内的第一行都有隐式的super();

当父类中没有空参数的构造函数时,子类必须手动通过super语句来指定要访问父类的构造函数。

当然,子类的构造函数第一行也可以手动指定this语句来访问本类的构造函数。

子类中至少有一个构造函数访问父类中的构造函数。

为什么superthis不能同时存在?

因为他们都需要写在第一行

为什么superthis都需要写在第一行?

因为初始化动作需要先做

4.6  final(最终)关键字

(1)final可以修饰类、方法、变量。

(2)final修饰的类不可以被继承。避免父类被子类复写。

(3)final修饰的方法不可以被覆盖。

(4)final修饰的变量是一个常量,只能被赋值一次。

(5)内部类只能访问被final修饰的局部变量。

常量的书写规范:所有字母都大写,如果有多个单词组成,则多个单词间通过“_”连接。

---------------------- android培训java培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net/heima

抱歉!评论已关闭.