花自飘零水自流。一种相思,两处闲愁。
——李清照《一剪梅》
## 1. 面向对象特性之继承
extends
1.1 继承定义
就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性,相同的行为,子类可以直接询问父类中的非私有的属性和行为
格式:class 子类 extends 父类{ … };
好处
提高代码的复用性
类与类之间产生了关系,是多态的前提
继承和成员变量的特点
- 不重名;无影响
- 重名:子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用
super
关键字,修饰父类成员变量。Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。
继承和成员方法的特点
- 不重名:如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。
- 重名:如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
1.2 方法重写
子类中出现与父类
一模一样的方法时
(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。重载和重写:
- 重载:方法名相同,参数列表不同。
- 重写:方法名相同,参数列表相同。两个方法分布在子类和父类中。 又叫方法的覆盖、覆写。
重写的最主要的目的:==对原有方法进行功能上的增强。==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 class Phone{
public void call(){
System.out.println("打电话");
}
public void show(){
System.out.println("显示号码");
}
}
class Px extends Phone{
public void show() {
super.show();
System.out.println("显示来电号码的归属地");
}
}
- ==方法的重写的特别注意:==
@override
检测当前注解下的(重写)方法是不是对父类方法进行了重写。- 访问权限:
public > protected >(default) > private
- 返回值类型
Object > String
- 父类中被重写的方法的访问权限 <= 子类的重写方法的访问权限。(==正常开发的时候父子类的访问修饰符都是相同的。==)
- 父类中被重写的方法的返回值类型要 >= 子类中被重写的方法的返回值类型。
/\/@override** 检测当前注解下的(重写)方法是不是对父类方法进行了重写。创建的是子类的对象,那么就优先使用的是子类的方法。所以重写才有意义。
1.4 继承格式
- 如果一个类没有使用extends 继承其他的类,那么默认继承的是Object. Object类是所有类的祖先。所有的类都继承了Object类。
- 子类继承了父类,那么子类就应该拥有了父亲的所有的属性和方法(局部变量,本类成员变量,父类的成员变量,继承的是父类成员属性和成员方法。)。
1.5 继承关系中-父子类构造方法的访问特点
子类的构造方法中有一个默认super()会调用,所以一定是先调用了父类的构造方法,然后才执行的子类的构造方法
子类的构造方法中可以通过 super( )来调用父类的构造方法。
super的在子类的构造器中的位置,必须是在第一语句上。而且子类的构造方法中只能有一个super调用。
总结:子类是必须调用父类构造方法。不写的话,默认添加一个super();写了的话,则调用指定的父类构造器。super只能有一个,而且必须是第一个语句。//正常来说 super只有在调用有参数的父类构造器的时候才会出现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 class Fu {
int num = 10;
public Fu(){
System.out.println("调用了父类的构造器,无can父类构造器");
}
public Fu(int num) {
System.out.println("调用了父类的构造器,有can父类构造器");
}
}
class Zi extends Fu{
int age = 10;
String name ="taoge";
public Zi(){
// super();
super(10);
//正常来说 super只有在调用有参数的父类构造器的时候才会出现。
// super();//子类构造器第一行默认有一个super调用了父类的构造器。 super可以不写,默认有,
// 但是如果写了,只能放在第一行。
System.out.println("调用了子类的构造器");
}
}
1.6 super和this
super:代表的是父类的存储空间(可以理解为父类的引用)
this:代表的是当前对象的引用
访问成员方法:
super.成员变量 父类的
this.成员变量 本类的
super.成员方法 父类的
this.成员方法 本类的
this(); //调用的本类的构造函数
super(); //调用的父类的构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 class Fu {
int num = 5;
}
class Zi extends Fu {
int num = 10;
public void method() {
int num = 30;
//30 局部变量
System.out.println("num = " + num);
//10 本类的成员变量
System.out.println("this.num = " + this.num);
//5 父类的成员变量
System.out.println("super.num = " + super.num);
}
public void methods(){
// 有对象调用 this 如果在不产生变量冲突的情况下,this可以省略
//System.out.println("num = " + this.num);//10
//10
System.out.println("num = " + num);
}
}
子类的每个构造方法中均有默认的super()调用父类的空参构造。
手动调用父类构造会覆盖默认的super()。
super() 和this();都在构造方法的第一行所以不能同时存在。
==只要创建子类的对象:父类的构造函数一定会被调用==。
子类的构造函数也一样会被调用,所以我们说:
创建对象一定会调用构造函数
。
1.7 继承的特点
Java自支持单继承,不支持多继承
Java支持多层继承(继承体系),顶层父类是Object类所有的类默认继承Object,作为父类。
子类和父类是一种相对的概念
1.8 抽象类
- 父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。
- 我们把没有方法主体的方法称为抽象方法。
- Java语法规定,包含抽象方法的类就是抽象类。
1.8.1 抽象方法
- 没有方法体的方法叫抽象方法。
public abstract void eat();
所以当前方法的方法体是没有任何作用的。- 抽象方法只有方法名,没有方法体。
- 非抽象方法,不需要重写,但是可以重写
1.8.2 抽象类abstract
- 包含抽象方法的类叫抽象类。
- Abstract class Animal抽象类是无法创建对象的。
- 因为每个子类都要去重写当前的方法
- 抽象类无法实例化对象:编译不通过。
- 一个类继承了抽象类的话,那么这个类应该实现抽象类(重写方法)
- 父类要有无参构造方法,如果不加构造方法,会报错。