8.5 继承-概述&特点
描述学生:
属性:姓名,年龄
行为:学习
public class Student {
private String name;
private int age;
public void study(){
System.out.println("study");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
描述工人:
属性:姓名,年龄
行为:工作
class Worker{
private String name;
private int age;
public void work(){
System.out.println("work");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试代码:
class ExtendsDemo{
public static void main(String[] args){
Student s = new Student();
s.setName("huanhuan");
s.setAge(14);
s.study();
}
}
将学生和工人的共享代码抽取到一个共性的类型中,这个类型中包含学生和工人。
class Person{
private String name;
private int age;
}
让学生和Person产生关系,就可以让学生使用Person中的共性的内容。通过一个关键字extends。
//Person类
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//Student类
public class Student extends Person{
public void study(){
System.out.println("study");
}
}
//Worker类
class Worker extends Person{
public void work(){
System.out.println("work");
}
}
class ExtendsDemo{
public static void main(String[] args){
Student s = new Student();
s.setName("huanhuan");
s.setAge(14);
s.study();
}
}
继承:
- 提高代码的复用性。
- 让类与类之间产生了关系。为第三个特性多态提供了前提。
8.6 继承-单继承和多继承
Java支持单继承,不直接支持多继承。
单继承:一个类只有一个父类
多继承:一个类可以有多个父类。Java并不直接支持。优势:可以让子类具备更多的功能。弊端:会产生调用不确定性,因为方法的主体不同,Java对其进行改良。
多层次继承:继承体系。学习一个继承体系时,先看顶层,了解该体系中具备的功能。使用时,找体系最下面的对象。
8.7 继承-什么时候继承
什么时候继承?
当事物存在着所属(is-a)关系时,可以通过继承来体现这个关系。xxx是yyy中的一种,xxx extends yyy
8.8 继承-私有的访问
对于父类中私有的部分,子类对象是无法直接访问的。
8.9 继承-成员变量的特点
子父类出现后,代码上的一些特点:
1.成员变量。
2.成员函数。
3.构造函数。
成员变量,注意的是原理。
当本类中出现了成员变量和局部变量重名的时候,用this区分。
当子父类中出现了重复的成员变量,使用super来区分。
8.10 继承-super关键字
super和this的用法很相似。
this:代表的是本类的对象的引用。
super:代表示父类的那一片空间。
8.10 继承-成员函数的特点-覆盖
子父类中的方法的特点:
特殊情况:当子父类中出现一模一样的方法时,子类对象运行的是子类的方法。这种特殊的情况称之为覆盖(override,复写,重写)。
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
**覆盖(重写)**是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值、函数名和形参都一样。
class Fu{
void show(){
System.out.println("fu");
}
}
class Zi{
void show(){
System.out.println("zi");
}
}
class ExtendsDemo{
public static void main(String[] args){
Zi z = new Zi();
z.show(); //输出zi
}
}
8.11 继承-覆盖的应用
描述手机:来电显示,打电话,发短信。
class Phone{
public void call(){}
public void sendMsg(){}
public void show(){
System.out.println("number");
}
}
class ExtendsDemo{
public static void main(String[] args){
Phone p = new Phone();
p.show();
}
}
手机出新了,来电功能更多了。
定义了来电显示功能,注意了,父类已经定义了来电显示功能,子类直接拿过来用就可以了。
但是子类对功能的内容要有自己的定义。保留父类功能的声明,建立子类功能特有的内容:覆盖的应用。
class Phone{
public void call(){}
public void sendMsg(){}
public void show(){
System.out.println("number");
}
}
class NewPhone extends Phone{
public void show(){
System.out.println("number"); //还可以改成super.show();
System.out.println("name");
System.out.println("pic");
}
}
class ExtendsDemo{
public static void main(String[] args){
NewPhone np = new NewPhone();
np.show();
}
}
输出:
number
name
pic
8.12 继承-覆盖的注意事项
- 子类方法覆盖父类方法,必须保证访问权限大于等于父类权限。(private<默认<public)
- 静态只能覆盖静态,或者被静态覆盖。
- 成员变量不存在覆盖,覆盖只用于函数。
8.13 继承-子类的实例化过程
-
子父类中的构造函数的特点。
创建子类对象时,父类中的空参数构造函数也运行了,因为子类中的所有构造函数的第一行默认都有一个隐式的super();语句。
调用本类中的构造函数中的this(实参列表)语句。调用父类中的构造函数用super(实参列表); -
为什么子类对象初始化都要访问父类中构造函数呢?
因为子类继承了父类中的内容,所以创建对象时必须要先看父类是如何对内容进行初始化的。
这就是子类的实例化过程。
8.14 继承-子类的实例化过程-注意事项
当父类中没有空参数构造函数时,子类需要通过显示定义super语句指定要访问的父类中的构造函数。
class Fu{
Fu(int x){
System.out.println("fu");
}
}
class Zi extends Fu{
Zi(){
super(1); //显示指定super的方式来访问父类中的构造函数
System.out.println("zi");
}
}
注意:用来调用父类构造函数的super语句在子类的构造函数中必须定义在第一行,因为父类的初始化要先完成。
class Fu{
Fu(int x){
System.out.println("fu");
}
}
class Zi extends Fu{
Zi(){
this(1); //是可以的,有了this语句,就没有super语句
System.out.println("zi");
}
Zi(int x){
super(2);
System.out.println("zi.....x");
}
}
问题:
- this和super用于调用构造函数,可以同时存在吗?
不可以,因为它们只能定义在第一行。 - 为什么要定义在第一行?
因为初始化动作要先执行行。
8.15 继承-子类的实例化过程-练习
class Person{
private String name;
private int age;
Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Student extends Person{
Student(String name,int age){
super(name,age); // 显示调用父类的构造函数
}
public void study(){
System.out.println("study");
}
}
class Worker extends Person{
Worker(String name,int age){
super(name,age); // 显示调用父类的构造函数
}
public void work(){
System.out.println("work");
}
}