一、什么是继承
1、继承的概念
举例理解:
根据打印机的原理,我们可以知道不管是彩色打印机还是黑白打印机,实现的都是一个功能:打印,这是二者的共性。彩色打印机和黑白打印机都继承了打印机的打印功能,且二者在打印机的基础上增加了自己特有的功能。
继承的概念:
程序员在保持原本特性的基础上进行扩展,增加新功能,产生的新的类,这种类称为派生类,也称为子类,被扩展的类被称为父类。 继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
2、代码示例
2.1 继承的语法
在Java中要表现类与类间的继承关系,需要借助extends关键字:
修饰符 class 子类 extends 父类 {
//…………
}
2.2 代码实现
例如:猫和狗都是动物,他们是动物这个类之下的细分。
class Animal {
// Animal 是 Cat、Dog 的父类
}
class Cat extends Animal {
// Cat 是 Animal 的子类
}
class Dog extends Animal {
// Dog 是 Animal 的子类
}
2.3 注意
1、子类会继承父类中的成员变量或成员方法。
2、子类继承父类后,必须要新添加自己特有的成员,体现出与父类的不同,否则就没有继承必要了。
class Animal {
// Animal 是 Cat、Dog 的父类
public void eat() {
System.out.println("吃吃吃");
}
}
class Cat extends Animal {
// Cat 是 Animal 的子类
public void cry() {
System.out.println("喵喵喵");
}
}
public class test1 {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat(); //Cat从Animal中继承了 eat方法,所以可以直接调用
cat.cry();
}
运行结果:
二、super、this 关键字
1、super
作用:在子类方法中访问父类的成员
代码示例:
class Base {
int a = 10;
public void methodA() {
System.out.println("Base————A");
}
}
class Child extends Base {
int a = 100;
public void methodA() {
System.out.println("Child————A");
}
public void method() {
System.out.println(a); //100
System.out.println(super.a); //10
methodA(); //Child————A
super.methodA(); //Base————A
}
}
总结:当想明确访问父类中成员时,借助super关键字即可
注意:只能在非静态方法中使用
2、this
作用:想明确访问本类的成员时,借助this关键字即可
代码示例:
class Base {
int a = 10;
public void methodA(int a) {
this.a = a;
//当前代码中有两个 a,使用this可以明确给成员变量 a 赋值为参数 a
}
}
3、super和this的相同与不同
相同点:
1、二者都是Java中的关键字
2、都只能在类的非静态方法中使用,用来访问非静态的成员方法和变量
3、在构造方法中使用时,必须是第一条语句,并且二者不能同时存在
不同点:
1、this是当前对象的引用,当前对象即调用实例方法的对象;super是子类对象中对父类继承下来的部分成员的引用
2、在非静态成员中:this用来访问本类的方法和属性;super用来访问父类继承下来的方法和属性
3、在构造方法中:this(…)用来调用本类的构造方法;super(…)用来调用父类的构造方法;二者不能同时出现
4、构造方法中一定会出现super(…)的调用,用户没有写编译器也会自动添加,而this(…)用户不写就没有
三、父子类成员访问顺序
1、子类中访问父类的成员变量
代码示例:
class Animal {
int age = 0;
double weight = 5.0;
}
class Cat extends Animal {
double weight = 9.5;
String color = "Black";
String name = "花花";
public void display() {
String name = "小黑";
System.out.println(age); //0
System.out.println(weight); //9.5
System.out.println(color); //Black
System.out.println(name); //小黑
}
}
总结:1、父类有子类没有的,访问从父类继承的成员变量
2、父类有子类也有的,访问子类自己的成员变量
3、父类没有子类有的,访问子类自己的成员变量
4、子类父类都没有的,编译报错
5、局部变量访问优先级高于成员变量
成员变量访问就近原则:自己有先访问自己的,自己没有再去父类中找
2、子类中访问父类的成员方法
2.1 成员方法名字不同
代码示例:
class Animal {
public void methodA() {
System.out.println("Animal————A");
}
}
class Cat extends Animal {
public void methodB() {
System.out.println("Cat————B");
}
public void method() {
methodA(); //Animal————A
methodB(); //Cat————B
//methodC();//编译报错
}
}
总结:成员方法名不同时,在子类方法中或通过子类对象访问时,优先访问自己的,自己没有的时候再到父类中找,如果父类中也没有,则报错。
2.1 成员方法名字相同
代码示例:
class Animal {
public void methodA() {
System.out.println("Animal————A");
}
public void methodB() {
System.out.println("Animal————B");
}
}
class Cat extends Animal {
public void methodA(int num) {
System.out.println("Cat————A");
}
public void methodB() {
System.out.println("Cat————B");
}
public void method() {
methodA(); //Animal————A
methodA(1); //Cat————A
methodB(); //Cat————B
}
}
总结:1、方法同名时,如果参数列表相同,则就近访问
2、如果参数列表不同,则根据参数选择合适的方法访问(方法的重载)
3、如果没有该方法就报错
四、父子类构造访问顺序
父子即先有父,后有子。子类对象构造时,需先调用父类的构造方法。
代码示例:
class Base {
public Base() {
System.out.println("Base构造方法");
}
}
class Child extends Base {
public Child() {
//super();
//没写时编译器会自动添加 且一定是方法中的第一条语句
System.out.println("Child构造方法");
}
}
所以当我们要实例化一个Child类的对象时,会先后输出:
因为在Child类的构造方法中,会自动添加super()在第一条语句,调用父类的构造方法。
所以我们可以知道,在我们构造子类对象时,先执行父类的构造方法,再执行子类的构造方法。
注意:
1、若父类定义无参或默认的构造方法,则在子类构造方法的第一条默认会有隐含的super()调用。
2、如果父类定义的是有参的构造方法,则在子类中一定要显示定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3、在子类构造方法中,super(…)调用父类构造时,必须为方法中第一条语句。
4、super(…)只能在子类构造中出现一次,不能与this(…)同时出现。