谦谦君子,温润如玉!桃李不言,下自成蹊!

why example

多态

1.多态概述

  1. 多态是继封装、继承之后,面向对象的第三大特性。
  2. 多态*现实意义*理解:
  • 现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是,即出现两种形态

  • Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

  • 3.多态体现为父类引用变量可以指向子类对象

    4.前提条件:必须有子父类关系。

    *注意:在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。*

    5.多态的定义与使用格式

​ 定义格式:父类类型 变量名=new 子类类型();

2.多态中成员的特点

  1. 多态成员变量:编译运行看左边

​ Fu f=new Zi();

​ System.out.println(f.num);//f是Fu中的值,只能取到父中的值

2.多态成员方法:编译看左边,运行看右边

​ Fu f1=new Zi();

​ System.out.println(f1.show());//f1的门面类型是Fu,但实际类型是Zi,所以调用的是重写后的方法。

public class Person {
    public void run(){
        System.out.println("run");
    }

    public void eat() {
        System.out.println("eat");
    }
}

public class Student extends Person{
    public void run(){
        System.out.println("son");
    }

    public void eat(){
        System.out.println("eat");
    }
}

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

        //一个对象的实际类型是确定的
        //new Student();
        //new Person();

        //可以指向的引用类型就不确定了:父类的引用指向子类

        //Student能调用的方法都是自己或者继承父类的
        Student s1 = new Student();
        //可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();//Student也是Person
        Object s3 = new Student();

        s2.run();//子类重写了父类的方法,执行子类的方fa
        s1.run();

        //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
        s2.eat();
        s1.eat();
    }
}
/*
输出结果
son
son
eat
eat
*/

注意事项:

  1. 多态是方法的多态,没有属性的多态:父可以吃,你也可以吃。但你和父的名字不一样
  2. 父类和子类有联系 类型转换异常!ClassCastException
  3. 存在的条件:继承关系,方法需要重写,父类引用指向子类对象!

static 方法:属于类,它不属于实例

final常量:无法重写

private方法:

3.多态性

java引用类型有两个

  编译时类型

  编译时类型由声明该变量时使用的类型决定

  运行时类型

  运行时类型由实际赋给该变量的对象决定

例:

 1 class Animal{
 2     public int month = 2;
 3     public void eat(){
 4         System.out.println("动物吃东西");
 5     }
 6     
 7 }
 8 
 9 class Dog extends Animal{
10     public int month = 3;
11     
12     public void eat() {
13         System.out.println("小狗吃肉");
14     }
15     
16     public void sleep() {
17         System.out.println("小狗睡午觉");
18     }
19 }
20 
21 class Cat extends Animal{
22     public int month = 4;
23     
24     public void eat() {
25         System.out.println("小猫吃鱼");
26     }
27 }
28 
29 public class Test {
30     public static void main(String[] args){
31         Animal a = new Dog();
32         Animal b = new Cat();
33         a.eat();
34         System.out.println(a.month);
35         //下面代码编译时会出错
36 //        a.sleep();
37         b.eat();
38         System.out.println(b.month);
39         
40     }
41 }

a对象编译时类型是Animal,运行时类型是Dog;

b对象编译时类型是Animal,运行时类型是Cat。

当运行时调用引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征,这就表现出:相同类型的变量调用同一个方法时表现出不同的行为特征,这就是多态。

该例中:当他们调用eat方法时,实际调用的是父类Animal中被覆盖的eat方法。

运行结果:

小狗吃肉
2
小猫吃鱼
2

上例中main方法中注释了a.sleep(),由于a的编译时类型为Animal,而Animal类中没有sleep方法,因此无法在编译时调用sleep方法。

对象的实例变量不具备多态性

上例中a,b对象分别调用了month,可以看到,其输出结果都是2

总的来说:

引用变量在编译阶段只能调用编译时类型所具有的方法,但运行时则执行他运行时类型所具有的方法。

4.多态的转型

  • 多态的转型分为向上转型和向下转型两种
  • 向上转型:多态本身就是向上转型过的过程

​ 使用格式:父类类型 变量名=new 子类类型();

​ 适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。

  • 向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型

​ 使用格式:子类类型 变量名=(子类类型) 父类类型的变量;

​ 适用场景:当要使用子类特有功能时。

java中向上转型的意义

首先了解多态

  • 使用父类类型的引用指向子类的对象;
  • 该引用只能调用父类中定义的非private方法和变量;
  • 如果子类中重写了父类中的一个方法,那么调用这个方法的时候,将会调用子类中的方法(动态绑定);
  • 变量不可以被重写,重写只针对方法,不重写变量;
  • 重写就是相同的方法,得到的结果和表现的形式不同;
//父类

public class Father{

	//父类有一个打孩子方法

	public void hitChild(){

	}
}

//子类1

public class Son1 extends Father{

	//重写父类打孩子方法

	public void hitChild(){

		System.out.println("为什么打我?我做错什么了!");

	}

}


//子类2

public class Son2 extends Father{

	//重写父类打孩子方法

	public void hitChild(){

		System.out.println("我知道错了,别打了!");

	}

}


//子类3

public class Son3 extends Father{

	//重写父类打孩子方法

	public void hitChild(){

		System.out.println("我跑,你打不着!");

	}

}


//测试类

public class Test{

	public static void main(String args[]){

		Father father;

		father = new Son1();

		father.hitChild();

		father = new Son2();

		father.hitChild();

		father = new Son3();

		father.hitChild();


	}



}

如果是Son1 a = new Son1();如果要改为son2那就很麻烦了,而father = new Son1();只需要改动一处。但是后面做大程序的时候,往往好几十个方法,如果你不用father,而用了son,那你一旦在写程序的时候发现这里应该用son2而不是son1,而你又没用father,那你这里一改就要改N多的地方,而且一改动很有可能会引发其他的错误,而且你这些方法很有可能又被其他的类所调用,那其他的类肯定也要跟着改啊,那这个改动量就非常大了。

向上转型的意义:程序开始的时候确定有一个father型对象,但是要根据用户的选择来决定他要被实例化成哪种类型的。但如果你要分开来声明的话,那你就因为不确定性必须要声明两个变量,分别来等待实例化。就是实例化的时候可以根据不同的需求实例化不同的对象,这也就是多态的意义。

5.多态案例:

例1:

package day0524;

public class demo04 {

    public static void main(String[] args) {


        People p=new Stu();

        p.eat();

        //调用特有的方法

        Stu s=(Stu)p;

        s.study();

        //((Stu) p).study();

    }

}

class People{

    public void eat(){

        System.out.println("吃饭");

    }

}

class Stu extends People{

    @Override

    public void eat(){

        System.out.println("吃水煮肉片");

    }

    public void study(){

        System.out.println("好好学习");

    }

}

class Teachers extends People{

    @Override

    public void eat(){

        System.out.println("吃樱桃");

    }

    public void teach(){

        System.out.println("认真授课");

    }

}

例2:

请问题目运行结果是什么?

package day0524;


public class demo1 {


    public static void main(String[] args) {


        A a=new A();


        a.show();


        B b=new B();


        b.show();


    }


}


class A{


    public void show(){


        show2();


    }

    public void show2(){


        System.out.println("A");


    }


}


class B extends A{


    public void show2(){

        System.out.println("B");

    }

}

class C extends B{

    public void show(){

       super.show();

    }

    public void show2(){

        System.out.println("C");


    }


}

答案:A B

posted @ 2020-09-27 20:06  FettersLove  阅读(115)  评论(0)    收藏  举报
Live2D