----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
封装性
封装性指在实际实现时,将复杂的内部结构隐藏起来,并为这组复杂的结构取一个统一的名称进行使用。在面向对象技术中,类是典型的封装性的体现,类将一组属性和功能组合成一个统一的结构,并使用类名来代表该结构。
封装性的最大优势在于隐藏每个类的内部实现(内部结构),从而既方便项目的分解也降低了项目的难度。这样可以在实际设计时,每个类都更注重自身的实现,而对于其它类的实现不需要深入了解。通常情况下,一般把类和类之间的关联性又称作耦合性,类和类之间的关联性比较低也称作耦合性比较低。
继承性
在程序设计中,很多设计出来的类也存在这样的包含关系,这样一个类的内部会包含和其它类类似的特征和属性,如果在设计时可以以另外一个类为基础进行设计,这个特性就是面向对象设计中的继承性。在一个项目中,如果类和类之间存储包含关系,即一个类是另外一个类的一种,就可以使用继承。
(1)继承语法
在Java语言中,继承的语法格式比较简单,如下所述:
访问控制符 [修饰符] class 类名 extends 父类名{
}
在声明类时,声明该类的继承关系,使用 extends 关键字实现,其中 extends 关键字前面是声明出的新类名,extends 关键字后面的类名是被继承的类名,要求被继承的类名已存在。Java 语言采用的是单重继承,也就是说一个类只能有一个直接父类。在类声明时,如果没有使用 extends 关键字声明父类,则自动继承 Object 类。说明:Object 类是系统提供的类,该类已存在。
示例代码如下:
//Animal.java
public class Animal {
/**类型名称*/
String name;
/**移动方式*/
int moveType;
}
//Mammalia.java
public class Mammalia extends Animal{
/**哺育时间*/
int fosterTime;
}
这里 Mammalia 类就是 Animal 类的子类,Animal 类就是 Mammalia 类的父类,子
类和父类具有相对性,同时类和类之间的继承具备传递性,就如现实中的血缘关系一样。
(2)继承说明
两个类之间如果存在了继承关系以后,将带来哪些不同呢?下面依次来进行说明:
子类拥有父类的所有属性
子类中继承父类中所有的属性,在父类中声明的属性在子类内部可以直接调用。
说明:如果访问控制符限制则无法访问。
子类拥有父类的所有方法
子类中继承父类中所有的方法,在父类中声明的方法在子类内部可以直接调用。
说明:如果访问控制符限制则无法访问。
子类不拥有父类的构造方法
子类不继承父类的构造方法,如果需要在子类内部使用和父类传入参数一样的构造方法,则需要在子类内部重新声明这些构造方法。
子类类型是父类类型
子类类型的对象可以自动转换为父类类型的对象,父类类型的对象则需要强制转换为子类的对象,转换的语法和基本数据类型转换的语法相同。
(3)方法覆盖
前面介绍了继承的一些基础知识,现在介绍一些在使用继承时需要注意的问题。
例如在实际的游戏中,会按照怪物的种类实现设计。首先设计一个基础类 Monster,然后按照怪物类别设计 Monster 的子类,如 Boss、NormalMonster 等。则在实际实现时,每个怪物都有移动(move)的功能,但是在 Boss 和 NormalMonster 的移动规则存在不同。这样就需要在子类的内部重新编写移动的功能,从而满足实际的移动要求。
该示例的实现代码如下:
//Monster.java
public class Monster{
public void move(){
//移动功能
}
}
//Boss.java
public class Boss extends Monster{
public void move(){
//Boss 类的移动规则
}
}
//NormalMonster.java
public class NormalMonster extends Monster{
public void move(){
// NormalMonster 类的移动规则
}
}
这样在 Monster 的每个子类内部都重新书写了 move 方法的功能,这种在子类内部重新父类中的方法的语法现象,称作方法覆盖。
在使用子类的对象时,子类内部的方法将覆盖从父类继承过来的方法,也就是说子类的对象调用的是子类的功能方法,而不是父类的方法。在进行方法覆盖时,子类内部的方法和父类的方法声明相同,而且子类方法的限制不能比父类的方法严格。例如不能使用比父类限制更大的访问控制符或抛出比父类更多的异常等,这个在实际使用方法覆盖时需要特别的注意。
(4) 需要注意的问题
除了方法覆盖以外,在实际使用继承时还有很多需要注意的问题。
1、属性覆盖没有必要
方法覆盖可以重写对应的功能,在实际继承时在语法上也支持属性覆盖(在子类内部声明和
父类属性名相同的属性),但是在实际使用时修改属性的类型将导致类结构的混乱,所以在
继承时不能使用属性覆盖。
2、子类构造方法的书写
该项是继承时书写子类最需要注意的问题。在子类的构造方法内部必须调用父类的构造方法,如果在子类内部不书写调用父类构造方法的代码时,则子类构造方法将自动调用父类的默认构造方法。而如果父类不存在默认构造方法时,则必须在子类内部使用 super 关键字手动调用。
说明:子类构造方法的参数列表和父类构造方法的参数列表不必完全相同。
3、子类的构造过程
在构造子类时由于需要父类的构造方法,所以实际构造子类的过程就显得比较复杂了。其实
在实际执行时,子类的构造过程遵循:首先构造父类的结构,其次构造子类的结构,无论构
造父类还是子类的结构,都是首先初始化属性,其次执行构造方法。则子类的构造过程具体
如下:
如果类 A 是类 B 的父类,则类 B 的对象构造的顺序如下:
类 A 的属性初始化
a)
类 A 的构造方法
b)
类 B 的属性
c)
类 B 的构造方法
d)
由于任何一个类都直接或间接继承自 Object 类,所以 Object 类的属性和构造方法都是首先执行的。
4、不要滥用继承
在实际的项目设计中,继承虽然很经常使用,但是还是不能滥用。
(5)如何设计继承
在实际的项目中,类和类之间的关系主要有三种:
1、没有关系
项目中的两个类之间没有关联,不需要进行消息传递,则这两个类之间就没有关系,可以互
相进行独立的设计。
2、使用关系(has-a)
如果一个类的对象是另外一个类的属性,则这两个类之间的关系是使用关系。例如把房屋
(House)看作是一个类,把门(Door)看成另外一个类,则房屋有一个门,代码的实现如下:
//House.java
public class House{
public Door door;
}
//Door.java
public class Door{
}
则这里 Door 的对象是 House 类的属性, Door 和 House 类之间的关系就是使用关系,则House使用 Door 类来制作自身。
使用关系提供了使用已有类来声明新类的方式,可以以组合的方式来构建更复杂的类,这是
项目中使用类的常见方式之一。判断是否是使用关系的依据就是:has-a,一个类具备另外一个类的对象,例如一个 House有一个门。
3、继承关系(is-a)
如果一个类是另外一个类的一种,也就是在分类上存在包含关系,则应该使用继承来实现。
例如 Boss 是怪物的一种,则使 Boss 继承 Monster 类。
下面简单介绍一些项目中继承的设计方法。在实际设计继承时,一般有两种设计的方法:
1、自上而下的设计
在实际设计时,考虑类的体系结构,先设计父类,然后根据需要来增加子类,并在子类的内
部实现或添加对应的方法。
2、自下而上的设计
在实际设计时,首先不考虑类的关系,每个类都分开设计,然后从相关的类中把重复的属性