## Java编程那些事儿62——继承(二)
郑州游戏学院陈跃峰
出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb)
##### 8.5.2.3 方法覆盖
前面介绍了继承的一些基础知识,现在介绍一些在使用继承时需要注意的问题。熟悉这些问题将更好的解决项目中的实际问题。
例如在实际的游戏中,会按照怪物的种类实现设计。首先设计一个基础类Monster,然后按照怪物类别设计Monster的子类,如Boss、NormalMonster等。则在实际实现时,每个怪物都有移动(move)的功能,但是在Boss和NormalMonster的移动规则存在不同。这样就需要在子类的内部重新编写移动的功能,从而满足实际的移动要求。该示例的实现代码如下:
~~~
//Monster.java
publicclass Monster{
publicvoid move(){
//移动功能
}
}
//Boss.java
publicclass Boss extends Monster{
publicvoid move(){
//Boss类的移动规则
}
}
//NormalMonster.java
publicclass [NormalMonster ]()extends Monster{
publicvoid move(){
//NormalMonster类的移动规则
}
}
~~~
这样在Monster的每个子类内部都重新书写了move方法的功能,这种在子类内部重新父类中的方法的语法现象,称作方法覆盖(override)。
方法覆盖在实际中保持了类的结构的统一,在实际使用时将极大的方便程序开发人员的使用,使项目的整体结构保持统一,便于项目的维护。
在使用子类的对象时,子类内部的方法将覆盖从父类继承过来的方法,也就是说子类的对象调用的是子类的功能方法,而不是父类的方法。
在进行方法覆盖时,子类内部的方法和父类的方法声明相同,而且子类方法的限制不能比父类的方法严格。例如不能使用比父类限制更大的访问控制符或抛出比父类更多的异常等,这个在实际使用方法覆盖时需要特别的注意。
在实际的项目中大量的存在需要在子类内部重写父类的功能方法的地方,恰当的使用方法覆盖将为项目开发带来很大的便利。
##### 8.2.2.4 需要注意的问题
除了方法覆盖以外,在实际使用继承时还有很多需要注意的问题。下面就这些问题进行一一说明。
1、 属性覆盖没有必要
方法覆盖可以重写对应的功能,在实际继承时在语法上也支持属性覆盖(在子类内部声明和父类属性名相同的属性),但是在实际使用时修改属性的类型将导致类结构的混乱,所以在继承时不能使用属性覆盖。
2、 子类构造方法的书写
该项是继承时书写子类最需要注意的问题。在子类的构造方法内部必须调用父类的构造方法,为了方便程序员进行开发,如果在子类内部不书写调用父类构造方法的代码时,则子类构造方法将自动调用父类的默认构造方法。而如果父类不存在默认构造方法时,则必须在子类内部使用super关键字手动调用,关于super关键字的使用将在后续进行详细的介绍。
说明:子类构造方法的参数列表和父类构造方法的参数列表不必完全相同。
3、 子类的构造过程
在构造子类时由于需要父类的构造方法,所以实际构造子类的过程就显得比较复杂了。其实在实际执行时,子类的构造过程遵循:首先构造父类的结构,其次构造子类的结构,无论构造父类还是子类的结构,都是首先初始化属性,其次执行构造方法。则子类的构造过程具体如下:
如果类A是类B的父类,则类B的对象构造的顺序如下:
a) 类A的属性初始化
b) 类A的构造方法
c) 类B的属性
d) 类B的构造方法
由于任何一个类都直接或间接继承自Object类,所以Object类的属性和构造方法都是首先执行的。
4、 不要滥用继承
在实际的项目设计中,继承虽然很经常使用,但是还是不能滥用,使用继承的场合以及相关问题参看下面的说明。
##### 8.5.2.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、 自下而上的设计
在实际设计时,首先不考虑类的关系,每个类都分开设计,然后从相关的类中把重复的属性和方法抽象出来形成父类。
对于初学者来说,第二种设计方式相对来说比较容易实现,所以一般初学者都按照第二种设计方式进行设计,设计完成以后再实现成具体的代码。
- 前言
- (1)序言
- (2)程序设计是什么?
- (3)你适合学习程序设计吗?
- (4)如何学好程序设计?
- (5)程序设计介绍小结
- (6)计算机软件基本概念
- (7)进制的概念
- (8)计算机内部的数据表达
- (9)网络编程基础
- (10)Java语言简介
- (11)JDK的获得、安装和配置
- (12)第一个HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基础使用进阶
- (15)如何学好Java语法
- (16)代码框架、关键字和标识符
- (17)基本数据类型
- (18)变量和常量
- (19)数据类型转换
- (20)空白、语句结束和注释
- (21)算术运算符
- (22)比较运算符
- (23)逻辑运算符
- (24)赋值运算符
- (25)位运算符
- (26)移位运算符
- (27)其它运算符
- (28)运算符优先级
- (29)表达式
- (30)流程控制基础
- (31)if语句语法(1)
- (32)if语句语法(2)
- (33)if语句语法(3)
- (34)switch语句语法
- (35)while语句语法
- (36)do-while语句语法
- (37)for语句语法
- (38)break和continue语句
- (39)流程控制综合示例1
- (40)流程控制综合示例2
- (41)流程控制综合示例3
- (42)流程控制综合练习
- (43)数组概述
- (44)数组基础语法
- (45)数组使用示例1
- (46)数组使用示例2
- (47)数组使用示例3
- (48)多维数组基础
- (49)多维数组使用示例1
- (50)多维数组使用示例2
- (51)多维数组练习
- (52)方法声明
- (53)方法声明示例
- (54)方法调用
- (55)方法重载和参数传递
- (56)方法练习
- (57)面向对象基础
- (58)类(一)
- (59)类(二)
- (60)对象
- (61)面向对象设计方法和面向对象特性(一)
- (62)继承(二)
- (63)多态性
- (64)访问控制符、修饰符和其它关键字
- (65)static修饰符
- (66)final修饰符
- (67)this和super
- (68)抽象类和接口(一)
- (69)抽象类和接口(二)
- (70)抽象类和接口(三)
- (71)内部类简介
- (72)包的概念
- (73)JDK文档使用
- (74)java.lang包介绍1
- (75)String类使用
- (76)StringBuffer类和System类
- (77)包装类
- (78)时间和日期处理
- (79)Random随机处理
- (80)集合框架简述
- (81)异常处理概述
- (82)异常处理语法1
- (83)异常处理语法2
- (84)IO简介
- (85)IO类体系
- (86)文件操作之File类使用
- (87)文件操作之读取文件
- (88)文件操作之写文件
- (89)读取控制台输入
- (90)装饰流使用1
- (91)装饰流使用2
- (92)IO使用注意问题
- (93)多线程基础
- (94)多线程实现方式1
- (95)多线程实现方式2
- (96)多线程使用示例1
- (97)多线程使用示例2
- (98)多线程问题及处理1
- (99)多线程问题及处理2
- (100)多线程问题及处理3
- (101)网络编程概述
- (102)网络编程技术1
- (103)网络编程技术2
- (104)网络编程技术3
- (105)网络编程技术4
- (106)网络编程技术5
- (107)网络协议概念
- (108)网络编程示例1
- (109)网络编程示例2
- (110)网络编程小结