1.多态的定义:多态是在继承/实现情况下的一种现象,表现为:对象多态,行为多态。

S和T都继承于P类,S和T都有run()方法,T类是经过方法重写的,

P p1 = new S();

p1.run();

P p2 = new T();

p2.run();

多态的前提:存在继承/实现关系;存在父类引用子类对象;存在方法重写。

public class test {
    public static void main(String[] args) {
        people p1 = new teacher();//编译看左边,运行看右边
        p1.run();
        System.out.println(p1.name);//输出为people,这里输出是people是因为teacher和student都继承了people,但是没有重写name属性,所以调用的还是父类的name属性

        people p2 = new student();
        p2.run();
        System.out.println(p2.name);//输出为people
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
public class student extends people{
    public String name = "student";
    @Override
    public void run(){
        System.out.println("student is running");
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
public class teacher extends people {
    public String name ="teacher";
    @Override
    public void run() {
        System.out.println("teacher is running");
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
public class people {
    public String name = "people";
    public void run() {
        System.out.println("people is running");
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

2.使用多态的好处

(1)在多态模式下,右边对象是解耦合的,更便于扩展和维护。

使用上边的例子,就是可以把new student改成new teacher 。

(2)定义方法时,使用父类类型的形参,可以接受一切子类对象,扩展性更强,更便利。

public static void go(people p){
    //使用people既可以接受student也可以接受teacher
}
  • 1.
  • 2.
  • 3.

3.多态下不能使用子类的独有功能。

示例

public class test {
    public static void main(String[] args) {
        people p1 = new teacher();//编译看左边,运行看右边
        p1.run();
        System.out.println(p1.name);//输出为people,这里输出是people是因为teacher和student都继承了people,但是没有重写name属性,所以调用的还是父类的name属性
        
        people p2 = new student();
        p2.run();
        System.out.println(p2.name);//输出为people
        //p2.study();//报错,多态下存在的问题,student和teacher都继承了people,但是student没有重写study方法,所以调用的还是父类的study方法
    }
    public static void go(people p){
        //使用people既可以接受student也可以接受teacher
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
public class student extends people{
    public String name = "student";
    @Override
    public void run(){
        System.out.println("student is running");
    }
    public void study(){
        System.out.println("student is studying");
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

解决方法:类型转换

(1)自动类型转换:父类 变量名 = new 子类();    people p = new teacher();

(2)强制类型转换:子类 变量名 = (子类)父类变量; teacher t = (teacher)p;

存在继承关系就可以在编译阶段强制类型转换,运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastExcaption)。

student s1 = (student) p2;
s1.study();
  • 1.
  • 2.

但是如果按照下面第十三行写法会报错,因为P2时student对象,两个子类不能互相转。

public class test {
    public static void main(String[] args) {
        people p1 = new teacher();//编译看左边,运行看右边
        p1.run();
        System.out.println(p1.name);//输出为people,这里输出是people是因为teacher和student都继承了people,但是没有重写name属性,所以调用的还是父类的name属性

        people p2 = new student();
        p2.run();
        System.out.println(p2.name);//输出为people
        //p2.study();//报错,多态下存在的问题,student和teacher都继承了people,但是student没有重写study方法,所以调用的还是父类的study方法
        student s1 = (student) p2;
        s1.study();
        teacher t1 = (teacher) p2;//报错
    }
    public static void go(people p){
        //使用people既可以接受student也可以接受teacher
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

面向对象高级之  多态 抽象_System

解决方法:instanceof关键字

if(p2 instanceof student) {//使用instanceof关键字判断是否是student类型
    student s2 = (student) p2;
    s2.study();
}else{
    teacher t2 = (teacher) p2;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
public class test {
    public static void main(String[] args) {
        people p1 = new teacher();//编译看左边,运行看右边
        p1.run();
        System.out.println(p1.name);//输出为people,这里输出是people是因为teacher和student都继承了people,但是没有重写name属性,所以调用的还是父类的name属性

        people p2 = new student();
        p2.run();
        System.out.println(p2.name);//输出为people
        //p2.study();//报错,多态下存在的问题,student和teacher都继承了people,但是student没有重写study方法,所以调用的还是父类的study方法
        student s1 = (student) p2;
        s1.study();
//        if(p2 instanceof student) {//使用instanceof关键字判断是否是student类型
//            student s2 = (student) p2;
//            s2.study();
//        }else{
//            teacher t2 = (teacher) p2;
//        }
//       // teacher t1 = (teacher) p2;
        System.out.println("--------------");
        student s2 = (student) p2;
        go(s2);
        teacher t2 = (teacher) p1;
        go(t2);

    }
    public static void go(people p){
        //使用people既可以接受student也可以接受teacher
        p.run();
        if(p instanceof student){
            student s = (student) p;
            s.study();
        }else{
            teacher t = (teacher) p;
            t.teach();
        }
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

上面代码20行往下运行结果:

面向对象高级之  多态 抽象_父类_02

4.final关键字

面向对象高级之  多态 抽象_多态_03

package com.lzk.test;


import java.util.Random;
import java.util.Scanner;

public class test {

    public static final String str = "hello world";  //这里一定要赋值,而且下面不能再改
    public static void main(String[] args) {
        final int a ;
        a = 10;
      //  a = 11; // 报错,不能修改final变量


    }

    public static void test1(final int b) {//b不能修改
        //b = 20; // 报错,不能修改final变量

    }
    final int[] arr = {1,2,3};
   // arr = null;// 报错,数组地址不能修改
   // arr[1] = 10; // 报错,数组不能修改
    final class A{

    }

    class C {
        public final void test() {

        }
    }

    class B extends C {
//        @Override   报错,因为父类final修饰了方法,子类不能重写
//        public void test(){
//    }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.

面向对象高级之  多态 抽象_多态_04

public class ContantTest {
    public static final String SCHOOL_NAME = "Beijing University";//常量名一般使用大写英文字母加下划线
}
  • 1.
  • 2.
  • 3.

面向对象高级之  多态 抽象_System_05

5.抽象类:abstract

面向对象高级之  多态 抽象_多态_06

public class test {


    public static void main(String[] args) {
        A a = new A();//报错
        a.run();
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
public abstract class A {// 2.定义一个抽象类A,带abstract关键字
    public abstract void run();// 1.定义一个抽象方法,没有大括号,class A要带abstract关键字

    public A(){

    }


}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

6.抽象类的好处

面向对象高级之  多态 抽象_System_07

面向对象高级之  多态 抽象_多态_08

特点是在调用时必须进行重写。

7.抽象类的应用场景

解决方法中的重复代码。

public class test {


    public static void main(String[] args) {
        teacher t = new teacher();
        t.write();

        student s = new student();
        s.write();
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
public abstract class people {

    public void final write(){//加上final方法防止被子类重写
        System.out.println("writing");
        System.out.println("writing1");
        System.out.println(writemain());
        System.out.println("writing2");
    }
    public abstract String writemain();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
public class student extends people{
    @Override
    public String writemain() {
        return "I write xxx.";
    }


}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
public class teacher extends people {
    @Override
    public String writemain() {
        return "I write essays.";
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

面向对象高级之  多态 抽象_父类_09

将中间不重复的地方换成抽象类重写代码。