面对对象的三大特性: 三、多态

多态

动态编译类型 - 同一方法可以根据发送对象的不同而采用多种不同的行为方式。

一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。

多态存在的条件

  • 有继承关系
  • 子类重写父类方法
  • 父类引用指向子类对象

注意:多态是方法的多态,属性没有多态性

instanceof

一个对象的实际类型是确定的

new Student();

new Person();

但是,可以指向的引用类型就不确定了

子类重写了父类的方法,就执行子类的方法

多态注意事项

  1. 多态是方法的多态,属性无法多态
  2. 父类和子类,有联系,类型转换异常! ClassCastException!
  3. 存在条件: 有继承关系,如有需要方法需要重写,父类引用指向子类对象! Father f1 = new Son();

无法被重写的方法(修饰符):

  • static 静态方法 - 方法,属于类,而不属于实例

  • final 常量

  • private 私有方法也不能被重写

被这三个修饰符修饰的方法无法被重写,所以也无法实现多态

如果没有“重写Override”,不能重复方法/方法名

  1. 父类Person
package oop.Demo06;

public class Person {
    public void run(){
        System.out.println("run");
    }
}
  1. 子类Student
package oop.Demo06;

public class Student extends Person {

    //重写在父类Person的run方法,从此父类子类都执行此处的方法
    @Override
    public void run() {
        System.out.println("son");
    }

    //父类Person没有这个方法-eat,因此在测试里,父类Person无法调用此方法
    public void eat(){
        System.out.println("eat");
    }
}
  1. 测试Application
package oop;

import oop.Demo05.A;
import oop.Demo05.B;
import oop.Demo06.Person;
import oop.Demo06.Student;

public class Application {
    public static void main(String[] args) {

        //一个对象的实际类型是确定的
        //new Student();
        //new Person(); new Person/Student后就是new Person/Student
        //但是,可以指向的引用类型就不确定了: 父亲的引用指向子类
        // 也就是 y与x, 多个x可以得到相同的y值

        //子类"Student"能执行的方法都是自己的或是继承父类的!
        Student s1 = new Student(); // 子类指向的引用
        //父类Person可以指向子类"Student",但是不可以调用子类独有的方法
        Person s2 = new Student(); // 父类指向的引用
        Object s3 = new Student(); //因为Person是student的父类,Object是默认的父类所以,可以newStudent以这三种形式
        //对象能执行那些方法,主要看对象左边的类型(父类、子类),和右边关系不大

        s2.run(); // 父类Person
        //s2.eat(); 无法调用
        s1.run(); //Student 类
        s1.eat();//子类可以调用自己的方法eat

        //输出结果为
        //son
        //son
        //都变成了son,经历过Override, 子类重写了父类的方法,就执行子类的方法
    }
}

1613629876

instanceof 关键词

instanceof (类型转换)

通过instanceof可以判断一个对象是什么类型

通过instanceof可以判断两个类之间是否存在父子关系

总结为公式:
System.out.println(x instanceof y); 编译器能否通过取决于x与y是否有父子类关系

怎么使用instanceof判断类与类之间的关系:

package oop;

import oop.Demo05.A;
import oop.Demo05.B;
import oop.Demo06.Person;
import oop.Demo06.Student;
import oop.Demo06.Teacher;

public class Application {
    public static void main(String[] args) {
        //Object > Person > Student//Teacher
        //Object > Person > Teacher
        //Object > String

        Object object = new Student(); //Object是Person的父类,Person是"Student"的父类
        //使用new在object和 Student 建立了这种关系,那么使用instanceof验证一下
        System.out.println(object instanceof Student); // True
        System.out.println(object instanceof Person); // True
        System.out.println(object instanceof Object); // True
        System.out.println(object instanceof Teacher); // False
        System.out.println(object instanceof String); // False

        System.out.println("========================");
        Person person = new Student();
        System.out.println(person instanceof Student); // True
        System.out.println(person instanceof Person); // True
        System.out.println(person instanceof Object); // True
        System.out.println(person instanceof Teacher); // False
        //System.out.println(person instanceof String); // False Person和String是平行关系,同级关系 !!编译器报错!!


        System.out.println("========================");
        Student student = new Student();
        System.out.println(student instanceof Student); // True
        System.out.println(student instanceof Person); // True
        System.out.println(student instanceof Object); // True
        //System.out.println(student instanceof Teacher); // False Student和Teacher是同级关系 !!编译器报错!!
        //System.out.println(student instanceof String); // False String和Student没有关系     !!编译器报错!!

        // 总结为公式:
        //System.out.println(x instanceof y); 编译器能否通过取决于x与y是否有父子类关系
    }
}

类型之间的转换

  1. 基本类型转换
  • 高-低 64 32 16 8
    • 高转低会有溢出,低转高没关系
  1. “类”型之间的转换
  • 父子之间的转换: 低转高没问题,高转低需要强制转换
  • 父类引用指向子类的对象
  • 子类转换为父类, 向上转型,无需强制转换
  • 父类转换为子类,向下转型,需要强制转换,子类可能会丢失自己的方法
  • 但是父类转换为子类,便利与方法的调用,减少重复的代码!

低转高是慢慢长大,高转低是返老还童,会失忆

//高                     低
Person student = new Student(); //子类Student这个对象被new成父类Person, 低转高 OK
//student.go();
//但是此时,student无法使用"Student"de方法go

//student[父类Person]将这个对象转换为Student[子类Student],我么就可以使用"Student"类型的方法了
Student student1 = (Student) student; //高转低, Person student -- Student student1 强制转换
((Student) student).go(); //经过强制转换就可以使用 更低一层-子类 的方法了

//子类转换为父类,可能会丢失一些自己的方法

/*
栗子:
Object example = new Student(); //低转高
Student example2 = (Student) example; //
((Student) example).go();
 */
posted @ 2021-02-18 15:34  NTE701  阅读(54)  评论(0)    收藏  举报
1