继承
基类和派生类
目的:代码的复用
关键词:extends
子类/派生类 extends 父类/基类/超类
public class A extends B{
//类 A继承了类 B
}
子类继承了除构造方法外的所有东西(包括属性和方法)
C++注释:java继承与C++类似,java用关键字extends代替了C++中的冒号(:),并且在java中都是公有继承,没有C++中的私有继承和保护继承。
super关键字
super代表父类的引用
super有三种用法:
1、super.data ; 父类的成员
2、super.func(); 父类的方法
3、super(); 父类的构造方法
用super调用父类的构造方法时,必须放在第一行(第一行有效)
子类构造方法
在子类构造方法中,要先帮父类进行构造
public class cat extends Animal{
private String voice;
public cat(String name,String sex,String voice) {
super(name,sex);//调用父类构造且必须放在第一行
voice ="喵"; //初始化子类数据成员
}
}
注意:
1、一个类如果被final修饰,这个类不能被继承-》密封类
2、继承最多不超过三层
3、基类只能访问自己的成员和方法
多态
向上转型 (子类-》父类)
向上转型发生的时机:
1、直接赋值
Animal animal=new Cat; // Cat 就是Animal的实例
2、方法传参
public class Test {
public static void main(String[] args) {
Bird bird = new Bird("花花");
feed(bird);
}
public static void feed(Animal animal) {
animal.eat("谷子");
}
}
//执行结果 花花正在吃谷子
//此时形参 animal 的类型是 Animal (父类),对应到的是Bird(子类)的实例
3、方法返回
public class Test {
public static void main(String[] args) {
Animal animal = myAnimal();
}
public static Animal myAnimal() {
Bird bird = new Bird("花花");
return bird;
}
}
//myAnimal返回的是Animal类型的引用,但实际对应的是Bird类型的实例
动态绑定
调用某个类的方法, 究竟执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 这个过程是程序运行时决定的(而不是编译期), 称为动态绑定
1、父类引用子类对象的时候
2、父类子类有同名覆盖方法 通过父类的引用调用同名的方法(super关键字)
public class Test {
public static void main(String[] args) {
Animal animal1 = new Animal("圆圆");
animal1.eat("谷子");
Animal animal2 = new Bird("扁扁");
animal2.eat("谷子");
}
}//animal和animal2虽然都是Animal的引用,但animal指向Animal实例,animal2指向Bird实例,所以调用eat方法时执行的程序不同
方法重写
重写:方法名相同 参数列表相同 返回值相同
重写注意事项:
1、方法不能是private
2、子类方法权限一定要大于父类方法权限 public权限最大
3、不能是一个静态方法(static)
访问权限示例:
public class Animal {
public void eat(String food) {
...
}
}
public class Bird extends Animal {
// 将子类的 eat 改成 private
private void eat(String food) {
...
}
}
//此时会编译出错,因为子类方法是private,父类是public
重写与重载的区别:
重写:方法名相同 、参数列表相同 、返回值相同的情况下, 对方法体进行修改或重写
重载:方法名相同、参数列表不同(参数类型不同、参数个数不同甚至是参数顺序不同),重载对返回类型没有要求
理解多态
一个引用能表现多种不同的形态
只写一些关于父类的代码,就能兼容子类的各种情况
class Shape { //父类,被继承
public void draw() {
// 啥都不用干
}
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("○");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("□");
}
}
}
///
// Test.java
public class Test {
public static void main(String[] args) {
Shape shape1 = new Cycle(); //向上转型
Shape shape2 = new Rect(); //向上转型
drawMap(shape1);
drawMap(shape2);
}
// 打印单个图形
public static void drawShape(Shape shape) {
shape.draw();
}
}
使用多态的好处:
1、类调用者对类的使用成本进一步降低
2、避免使用大量的 if - else
3、可扩展能力更强
向下转型 (父类-》子类)
向下转型就是父类对象转变为子类对象
相比于向上转型,向下转型不常见
Animal animal = new Bird("圆圆"); //向上转型
animal.eat("谷子");
animal.fly(); //Animal类中找不到 fly 方法
// 编译出错
向上转型,Animal animal=new Cat; Cat 就是Animal的实例
所以向下转型前要有向上转型
虽然 animal 实际引用的是一个 Bird 对象,但编译器查看的是Animal类中的方法,所以会编译出错