一、方法重写/覆盖(override)
1.1 基本介绍
1.2 快速入门
public class Animal {
public void cry() {
System.out.println("动物叫唤..");
}
}
public class Dog extends Animal{
//1. 因为 Dog 是 Animal 子类
//2. Dog 的 cry 方法和 Animal 的 cry 定义形式一样(名称、返回类型、参数)
//3. 这时我们就说 Dog 的 cry 方法,重写了 Animal 的 cry 方法
public void cry() {
System.out.println("小狗汪汪叫..");
}
}
注意:
1、子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类。
2、比如 父类 返回类型是 Object ,子类方法返回类型是 String。Object 不是 String 的子类,因此编译错误。
3、子类方法不能缩小父类方法的访问权限。public > protected > 默认>private
1.3 注意事项和使用细节
方法重写也叫方法覆盖,需要满足下面的条件
1.4 重写(override)和重载(overload)的区别
二、面向对象编程-多态
1.1 多[多种]态[状态]基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
1.2 多态的具体体现
- 方法的多态
public class PloyMethod {
public static void main(String[] args) {
//方法重载体现多态
A a = new A();
//这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));
//方法重写体现多态
B b = new B();
a.say();
b.say();
}
}
class B { //父类
public void say() {
System.out.println("B say() 方法被调用...");
}
}
class A extends B {//子类
public int sum(int n1, int n2){
//和下面 sum 构成重载
return n1 + n2;
}
public int sum(int n1, int n2, int n3){
return n1 + n2 + n3;
}
public void say() {
System.out.println("Asay() 方法被调用...");
}
}
结论:重写和重载就体现多态
- 对象的多态 (核心,困难,重点)
public class Animal { //父类
public void cry() {
System.out.println("Animal cry() 动物在叫....");
}
}
public class Cat extends Animal {//猫继承动物
public void cry() {
System.out.println("Cat cry() 小猫喵喵叫...");
}
}
public class Dog extends Animal {
public void cry() {
System.out.println("Dog cry() 小狗汪汪叫...");
}
}
public class PolyObject {
public static void main(String[] args) {
//体验对象多态特点
//animal 编译类型就是 Animal , 运行类型 Dog
Animal animal = new Dog();
//因为运行时,执行到该行时,animal运行类型是Dog,所以cry就是Dog的 cry
animal.cry(); //小狗汪汪叫
//animal 编译类型 Animal,运行类型就是 Cat
animal = new Cat();
animal.cry(); //小猫喵喵叫
}
}
1.3 多态注意事项和细节讨论
多态的前提是:两个对象(类)存在继承关系
- 多态的向上转型
//向上转型: 父类的引用指向了子类的对象
//语法:父类类型引用名 = new 子类类型();
Animal animal = new Cat();
Object obj = new Cat();// 可以 Object 也是 Cat 的父类
- 多态的向下转型
//多态的向下转型
//(1)语法:子类类型 引用名 =(子类类型)父类引用;
//(2)要求父类的引用必须指向的是当前目标类型的对象
//cat 的编译类型 Cat,运行类型是 Cat
Animal animal1 = new Cat();
Cat cat = (Cat) animal1;
//dog 的编译类型 Dog,运行类型是 Dog
Animal animal2 = new Dog();
Dog dog = (Dog) animal2;
属性没有重写之说!属性的值看编译类型
instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型
//BB 是 AA 子类
BB bb = new BB();
System.out.println(bb instanceof BB);// true
System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
//BB 是 AA 子类
AA aa = new BB();
System.out.println(aa instanceof AA); //true
System.out.println(aa instanceof BB); //true
1.4 java 的动态绑定机制(非常非常重要.)
Java 重要特性: 动态绑定机制
1、调用对象方法,方法会和该对象的 运行类型 / 内存地址 绑定.
2、调用对象属性,没有动态绑定机制,哪里声明,使用哪里的属性。
1.5 多态的应用
- 多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型。
// 应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、
// 让 Student 和 Teacher 都继承 Person。
// 2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象 say 方法
Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("mary", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);
- 多态参数
方法定义的形参类型为父类类型,实参允许为子类类型。(后面我们使用接口编程,一般都是子类类型)
本博客引用韩顺平老师Java课程