第七讲 类的继承
主要内容 无继承时类的复用 类继承实现代码复用 继承时方法的重写 super关键字 final修饰的数据、方法和类 |
无继承时类的复用
一个类借用其他类的服务
class Person{
public double employed(double salary){
return salary*0.8;
}
}
class Test {
double s;
Test(double x){s=x;}
public static void main(String[] a){
Person p=new Person();
Test t=new Test(1000);
System.out.println("He should get "+t.s);
System.out.println("But he only get "+p.employed(t.s));
}
}
结论:
² A类要用到B类的非静态方法时,可临时创建B类对象。
² 借由B类对象调用自身的方法,服务于A类对象。
类作为另外一个类的成员
class Person{
public double employed(double salary){
return salary*0.8;
}
}
class Test {
double s;
Test(double x){s=x;}
Person ps=new Person();
public static void main(String[] a){
Test p=new Test(1000);
System.out.println("He should get "+p.s);
System.out.println("But he only get "+p.ps.employed(p.s));
}
}
思考 1. 两个程序有什么区别? 2. Test类的对象怎么取用于Person类提供的服务? 3. 一个类从另一个类取用服务,有什么好处? 4. 如果Person类需要提供公共的服务,应作何改变? |
类继承实现代码复用
每个类都有父类
如果没有使用extends关键字,则Object类就是缺省的父类。
Object类包含在java.lang包中。所有的类都是从这个类继承而来的。
Object类定义和执行了在Java系统需要的所有类的行为。
类继承的实现
一个类能从其它类继承行为与属性,由此直接实现代码复用。
class SubClass extends SuperClass { ClassBody } |
程序一:
import javax.swing.*;
class Test extends JFrame{
public static void main(String[] aa){
Test t=new Test();
t.setVisible(true);
t.setSize(300,200);
}
}
程序二:
class Person{
int salary;
void employed(){
if (salary==0) System.out.println("no job");
else System.out.println("job");
}
}
class Children extends Person{
int age;
void printAge(){System.out.println("Age:"+age);}
public static void main(String[] aa){
Children c=new Children();
c.salary=560;
c.age=12;
c.printAge();
c.employed();
}
}
继承时的对象初始化
class Art{
Art(){System.out.println("Art constructor");}
}
class Drawing extends Art{
Drawing(){System.out.println("Drawing constructor");
}
}
class Cartoon extends Drawing{
Cartoon(){System.out.println("Cartoon constructor");}
public static void main(String[] aa){
new Cartoon();
}
}
静态变量初始化 | 运行父类的构造方法(默认或主动) (按级别高到低的顺序) | 实例变量初始化 | 调用主类的构造方法 |
思考
1. 一个类如何去继承另一个类? 1. 一个类继承另一个类时,究竟继承了什么? 2. 类的继承有什么好处? 3. 每个类都有父类吗? 4. 如果类定义时无extends部分,该类的父类是? 5. 多个子类可以继承自一个父类吗? 6. 一个类可以同时继承多个父类吗? 7. 若不希望父类中的某成员被子类所继承,如何实现? 8. 根类Object在哪个软件包中? 9. 对象的初始化时,父类的什么样的构造方法能自动执行? 10. 如何主动调用父类的构造方法? 11. 父类构造方法的执行时机? |
方法的重写(overriding)
当一个子类继承父类时,子类将自动拥有父类的成员变量和成员方法。
问题:如果父类的某个方法对于子类不合适怎么办?
练习:在继承Persons的子类Children中,重写employed方法,输出“A child should study in the school.”
重写方法设计要点
² 方法名相同,方法返回类型相同,参数相同
² 重写总是在父类和子类之间
² 重写的意义是修正覆盖父类方法
super关键字
是一个特殊的变量,提供了对父类的访问。
每个子类构造方法的第一条语句都是隐含的调用语句super(),如果父类没有这样形式的构造方法,则编译时会出错。
super(参数);--------引用父类的构造方法(构造方法不能被继承,要使用父类带参的构造方法时,必须主动调用)
super.变量------访问父类的成员变量
super.方法(参数);------调用父类的成员方法
程序一:
class A{
int x=1;
int y=2;
}
class B extends A{
int x=5;
B(){
System.out.println(x+y);
System.out.println(super.x+y);
}
public static void main(String[] aa){
new B();
}
}
程序二:
class GrandParent{
GrandParent(String s){
System.out.println("GrandParent "+s);
}
}
class Parent extends GrandParent{
Parent(String s){ super("Parent "+s); }
}
class Children extends Parent{
Children(String s){ super("Children "+s); }
public static void main(String[] a){
new Children("lili");
}
}
程序三:
class TestSuper{
int id;
TestSuper(int a){id=a; }
void identify(){System.out.println("SuperClass");}
}
class Tests extends TestSuper {
int id;
Tests(int a){ super(a);}
void identify() {
System.out.println("SubClass");
}
void test(){
System.out.println(id);
System.out.println(super.id);
identify();
super.identify();
}
public static void main(String[] aa){
(new Tests(5)).test();
}
}
思考 1. 如何调用父类的构造方法? 2. 调用父类构造方法语句应置于何处? 3. 什么时候需要调用父类的构造方法? 4. super.变量名与this.变量名,分别何意? |
练习:按照以下给出的步骤,逐步编程。
1. 设计一个Animal类,属性有重量、年龄,行为有:吃(eat)、睡(sleep)、呼吸(breathe)。
2. 创建继续Animal的子类fish,呼吸行为不同,改造其方法。
3. 在main方法中创建一个fish对象,执行吃、睡、呼吸的方法,执行程序理解重写。
4. 分别给Animal类和fish类创建一无参构造方法。编译执行,分析结果。
5. 改fish类的构造方法带参,编译执行并分析结果。
final修饰的数据、方法和类
final数据
final 类型 标识符;
如:final double PI=3.14159;
final Circle c=new Circle(5);
final数据意义
² 常数——当类型是基本数据型时
² 不变的对象引用——当类型是对象时
程序一:
class TestFinal{
final double A=5;
final int B;
public static void main(String[] aa){
TestFinal t=new TestFinal();
System.out.println(t.A++);
System.out.println(t.B);
}
}
程序二:
class Fin{
static int num;
Fin(){
num++;
System.out.println("Fin"+num);
}
}
class TestFinal{
public static void main(String[] aa){
final Fin f=new Fin();
f=new Fin();
}
}
final方法
final方法是不可重写的方法。
final 类型 方法名(参数名){…};
class Fin{
final void A(){System.out.println("Fin.A()"); }
}
class TestFinal extends Fin{
void A(){System.out.println("TestFianl.A()");}
public static void main(String[] aa){
new TestFinal().A();
}
}
final类
final类是不可继承的类。
final 类型 类名{…};
如:String类就是一个final类。
说明:类的说明中,习惯上将public等权限修饰符置于final之前。
如:public final class Test{}
final class A{ //final去掉再试
A(){System.out.println("new A()");}
}
class B extends A{
B(){System.out.println("new B()");}
public static void main(String[] aa){
new B();
}
}
思考 1. 如何定义一个常数? 2. final修饰的对象引用有何特别的意味? 3. final方法一定要在final类中定义吗? 4. 如果一个类的方法不允许子类改写,如何设置? 5. final类可以被继承吗? 6. final限制了还是拓广了类的复用? 7. 何时考虑将一个类设定为final类? |