Java作为面向对象程序语言具有十分优秀的扩展能力,Java中提供了多种机制对程序功能进行扩展,如继承,组合,多态,接口,内部类,灵活使用这些机制能使程序结构易于扩展,适用性强,性能优化并且代码优雅——Java语言程序设计
继承
继承的基本思想:基于某个父类的扩展,定制出一个新类,子类可以继承父类中的原有属性和方法,也可以扩展出父类不具有的属性和方法,或对父类中的某些方法进行重写。
【1】extends关键字:publicclassPad3 extends Computer3
【2】方法的重写(覆盖):StringsayHello(){// 子类重写父类方法
returnsuper.sayHello()+"平板电脑";// 调用父类方法,在其结果后添加字符串
}
(1)保留父类成员的名称
(2)重新编写方法成员的实现内容
(3)更改成员方法的访问权限:重写时只能降低访问限制,由private到public,不能由public到private
(4)重写父类方法的返回类型:重写的的返回值类型必须是父类中同一方法返回值类型的子类,如果返回值类型为基本数据类型,则返回值必须与父类相同(基本数据类型没有子类),否则(The return type is incompatible with)
(5)重构:父类与子类的成员方法返回值,方法名称。参数类型及个数完全相同,仅有实现内容不同
(6)如用父类声明子类的对象(Computer2computerpad= new Pad2();
),则对象所调用的方法实现的是子类重写后的方法
【3】super关键字
(1)在子类中,如果有程序调用子类重写的函数,则实现结果为重写后的结果,如要使用父类的结果,则使用(super.)调用父类的方法( super.sayHello();)
【4】继承关系下的构造方法
(1)在实例化子类对象时会在子类的构造方法中自动在第一行调用父类的无参构造方法(如果存在),如果父类不存在无参构造,则子类初始化时必须在构造函数的第一行显示调用父类的有参构造并传入父类要求的参数(即相当于子类无法进行无参构造,故在父类中设置无参构造对继承很有意义)
(2)如果父类也有父类,则在第一行super()中包含父类继承其父类的super()
【5】继承的实现:以Base和Sub为例
发生继承关系时父类的数据 | hiding | overriding | 编译阶段 | 运行阶段 |
数据成员 | * | 检查语法,确定成分对象 | 按照编译结果直接执行 | |
成员方法-类方法 | * | 检查语法,确定成分对象 | 按照编译结果直接执行 | |
成员方法-实例方法 | * | 检查语法 | 按照调用方法的对象的实际类型来选择方法执行 | |
super.method() | 检查语法,确定成分对象 | 按照编译结果直接执行 |
public class Base {
public int number;
public String name;
public Base() {
this(1);
}
public Base(int num) {
this(num, "base_intial");
}
public Base(int n, String name) {
number = n;
this.name = name;
}
public int getNumber() {
return number;
}
public String getName() {
return name;
}
}
public class Sub extends Base {
public String name;
public Sub() {
this("sub_initial");
}
public Sub(String name) {
this(2, name);
}
public Sub(int number, String name) {
super(number);
this.name = name;
}
public int getNumber() {
return number;
}
public String getName() {
return name;
}
public String getSuperName() {
return super.getName();
}
public String getThisName() {
return this.getName();
}
}
Base base = new Base(); //静态绑定对应类调用对应方法
base.number=1
base.name=base_intial
base.getNumber():1
base.getName():base_intial
Sub sub = new Sub();//静态绑定对应类调用对应方法
sub.number=2
sub.name=sub_initial
sub.getNumber():2
sub.getName():sub_initial
((Base)sub).getName()=sub_initial//将子类对象强制转化成父类,相当于向上转型
sub.getSuperName():base_intial
sub.getThisName():sub_initial
base = sub;//将子类的对象赋给父类的对象,即把子类按照父类的形式表示
base.number=2//因为父子类中均有number,子类的number是从父类继承而来,子故此时相当于super.number=sub.number,赋值后父类的number被改变,因为数据成员运行结果只依赖编译结果,故base.number=2
base.name=base_intial//根据上表,子类继承父类时父类的数据成员会被隐藏,sub在定义时重新定义了name,相当于sub中有三个数据成员,他继承父类的number和name,以及他自己的name,因为父类只能调用子类中继承自父类的数据,故此时super.name=base.name,因为数据成员运行结果只依赖编译结果,故base.name=base_intial,此时对于sub.name相当于被隐藏
((Sub)base).name=sub_initial//将父类对象强制转化为子类对象,此时相当于sub.name被解除隐藏,根据编译结果sub.name=sub_initial
base.getNumber():2//
base.getName():sub_initial//因为对base中的getName来说是获得this.name,因为sub重新定义了name,此时this.name为sub自身的name,即sub.name=sub_initial