在Java编程中,会遇到很多类别的属性相同、方法相似。例如编辑属性都只有名称,学习方法名称相同却有所差别的Student类时:
UNStudent { String name; study(){} } //大学生类
GStudent { String name; study(){} } //高中生类
……
多次定义这种类似的类会浪费大量的时间。所以在Java编程中,我们可以使用类的继承来节约时间,提高编写代码的利用率。
1.Java中类的继承的格式:
(1)关键字 extends
(2)具体写法:
权限 class 类名(子类、派生类、超类) extends 类名(父类、基类) {
}
2. 现实生活中什么关系需要使用继承来实现?
父母子女的关系。
包含关系。
3. 子类继承到了父类的那些内容?
子类继承到父类所有的属性和方法。
注意:父类中private修饰符修饰的属性和方法能被子类直接继承但是不能被直接使用。
父类中需要定义setter和getter方法。
在子类中调用setter方法进行赋值。
所以权限修饰符不影响继承,只影响使用。
拓展:
public、protected、默认的、private这四个访问修饰符是用来限制属性和方法在什么样的情况下可以使用。
访问修饰符 |
同类中 |
同包中 |
不同包中 |
不同包中但是有继承关系的子类中 |
private |
可以 |
不可以 |
不可以 |
不可以 |
默认的 |
可以 |
可以 |
不可以 |
不可以 |
protected |
可以 |
可以 |
不可以 |
可以 |
public |
可以 |
可以 |
可以 |
可以 |
4.方法的重写:
在运用类的继承时,有时会出现子类的方法中参数个数与类型一样与父类相同,但是具体的操作却与父类不同。此时就要运用方法的重写功能。
举一个生活中的例子:
父母有一个学习方法,子女也有一个学习方法,但是这两个方法不是完全一致的。
父类中:
public void study(String name, int score) {
this.score += score;
System.out.println(this.name + "在学习" + name + "中,学分是" + this.score);
}
子类中:
public void study(){
System.out.println(getName()+"是大学生,学习方法不同啦!");
}
以上为方法的重写。
观察以上代码可以发现,方法重写的实现条件是:
1.必须要存在继承关系。
2.方法的返回值类型,方法名,参数都必须要和父类的完全一致。
3.子类重写方法的访问修饰符可以大于或者等于父类方法的访问修饰符。
4.方法中的代码必须要不同。
关于重写后方法的调用:
使用时先实例化对象,根据new关键字后的类名来决定的,如果类名是子类的,那么优先调用子类的方法,如果子类没有才会去调用父类中的方法。
5.自动转型:
观察下面这个例子:
从知识储备量的角度上来讲,大学英语教师可以教高中生、初中生、小学生。但是各个阶段学生自己学习英语的方法有所不同,该实例用代码实现如下:
UNStudent { String name; study(){} }
GStudent { String name; study(){} }
CStudent { String name; study(){} }
XStudent { String name; study(){} }
......
不难发现每分一个类就需要重新定义一个方法,十分浪费时间和电脑存储空间,利用方法的重写可以完成以下修改:
Student {String name; study(){}}
UNStudent extends Student { study(){} }
GStudent extends Student { study(){} }
CStudent extends Student { }
XStudent extends Student { }
……
这样每定义一个新的类只需要重写有修改的方法,十分简洁。
但是针对老师教导学生的方法,代码实现如下:
Teacher {
teach(UNStudent un) { un.study(); }
teach(GStudent un) { un.study(); }
teach(CStudent un) { un.study(); }
teach(XStudent un) { un.study(); }
......
可以发现,即使在学生类中使用了继承与重写,但是书写老师教书方法时依旧十分麻烦。
现在做出如下修改:
teach(Student stu){
stu.study();
}
在教师教书方法中只带入学生父类的参数。
在主函数中通过带入继承了学生父类的不同学生子类参数来达到实现方法的目的:
t.teach(un);//带入UNStudent类的实例化对象un
t.teach(stu);//带入Student类的实例化对象stu
结果发现带入子类则生成子类的运行结果,带入父类则生成父类的运行结果。
以上称为自动转型。
自动转型的一般格式:
(1)父类名 对象名 = new 子类构造方法(参数值,...);
(2)public void method(父类名 参数名){
}
子类名 对象名a = new 子类构造方法(参数值,...);
父类名 对象名b = new 子类构造方法(参数值,...);
method(对象名a);
method(对象名b);