Java学习19-- 多态Polymorphism

Java中的多态(Polymorphism)是面向对象编程的三大特性之一,另外两个是封装(Encapsulation)和继承(Inheritance)。多态允许你使用一个接口来表示多种数据类型。

在Java中,多态主要体现在以下几个方面:
Overloading+Overriding+Upcasting+Downcasting

  • 方法的重载(Overloading):在同一个class中,method名相同,但参数列表(参数类型、个数或顺序)不同的多个方法。

public class Example {  

    void show(int x) {  

        System.out.println("整数:" + x);  

    }  

  

    void show(double x) {  

        System.out.println("双精度:" + x);  

    }  

}
  • 方法的重写(Overriding):child class可以覆盖parent class中的method,即child class和parent class有相同名称、相同参数列表和相同return类型的method。当子类object调用这个method时,会按照child class中的method执行,而不是parent class中的同名method执行。

class Parent {  

    void show() {  

        System.out.println("Parent's show()");  

    }  

}  

  

class Child extends Parent {  

    @Override  

    void show() {  

        System.out.println("Child's show()");  

    } 

     void childplay() {

            System.out.println("Child's playing");

        }


}
  • 对象的向上转型(Upcasting):(只应用于non-static method)定义好的parent类型的变量p,虽然指向了child class,但依旧只能调用父类中独有的non-static method,而不能调用child class独有的method。

Parent p = new Child();  

p.show();  // 调用Parent类的show()方法

//知识补充downcasting:更多详见下例
 ((Child)p).childplay();//调用子类独有的childplay method,只能先强制转换成子类 ((Child)p),然后再调用childplay method
  • 对象的向下转型(Downcasting):将parent class类型的变量转换为子类类型child class。这需要明确地进行类型转换,并且只有在运行时该对象确实是子类的实例时,转换才会成功。引用类型之间的类型转换,关键字instanceof(参见下面举例)

if (p instanceof Child) {  //如果 object p 是Child class的子类,那么括号内为true
//这个例子中 object p属于Parent类型,同时保留了部分Child class的特质,所以if (p instanceof Child)这句判断得到true
//如果有第三个Kids class extends Child class 同时 Parent p1 = new Child(); 那么语句if(p1 instanceof kids)会获得false

    Child c = (Child) p;  //object p 是按照 Parent class定义的,这里强制类型转换为Child class

    c.show();  // 调用Child类的show()方法
    //其实上面两句可以合写成一句,写做 ((Child)p).show();

}

多态的主要好处是提高代码的灵活性和可扩展性。例如,你可以定义一个方法,该方法接受一个父类类型的参数,然后在运行时传递子类(们)的对象。这样,你可以在不知道具体子类类型的情况下调用该方法,但方法内部会根据对象的实际类型执行相应的操作。这种特性在设计模式(如工厂模式、策略模式等)中经常被用到。

备注:不可重写override的几种情况

  1. static 方法,属于class直接预加载了,都用不到method来跑
  2. final 定义了的常量,不能再改了,比如 final double PI = 3.14;
  3. private method
  • 动态编译:类型 可扩展性
    即同一method可以根据object的不同而采用多种不同的行为方式
    一个对象的实际类型是确定的,但可以指向对象的引用类型有很多

注意观察这句程序块在下面例子的应用


        //一个对象的实际类型是确定的
        // Student s1
        // Person s2

        //但是其指向的引用类型就不确定了
        Student s1= new Student();
        Person s2= new Student();

程序举例


package oop;
import oop.Demo06.Person;
import oop.Demo06.Student;

public class Application {

    public static void main(String[] args) {
        //一个对象的实际类型是确定的
        // s1 Student();
        // s2 Person();


        //实际类型是Student()但是其指向的引用类型就不确定了
        //Student能调用的方法都是自己的或者继承父类的
        Student s1= new Student();
		
        Person s2= new Student();//父类的引用指向子类的类型
        //Person父类,可以指向子类,但是不能调用子类独有的方法

        Object s3= new Student();
		// Object父类,可以指向子类,但是不能调用子类独有的方法,

        s1.run();//
        s2.run(); //这里父类和子类都有run method,父类触发method run,最后运行的子类student run,属于同名method override
        //如果子类重写了父类的同名方法,那么执行子类的方法就好
        //s3.run(); //object父类里面没有run method,调用run失败

        s1.eat();
        //s2.eat(); 没法使用,因为父类person里面并没有eat这个方法
        //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
        ((Student)s2).eat();//如果实在想用,强制类型转换成Student类型后再用

    }
}


package oop.Demo06;

public class Student extends Person{

    public void run(){
        System.out.println("student is running");
    }

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

}


package oop.Demo06;

public class Person {

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

}


运行结果:


student is running
student is running
student is eating
student is eating

多态注意事项:

  1. 多态是方法的多态,属性没有多态
  2. 父类和子类这种有继承关系才可以,比如子类重写父类方法,父类引用指向子类对象;没有关系的两种,如果强制类型转换,那么会报错类型转换异常,报错ClassCastException
  3. 多态存在的必要条件:继承关系,方法需要重写。父类指向子类对象!father f1 = new Son();

详解 instanceof 父子关系判断关键字

instanceof是什么:
object_a instanceof class_A是 Java 中是Java中的二元运算符,用于测试一个object_a是否是指定class_A的实例或其子类child class的实例。它返回一个布尔值,如果对象是给定类型的实例,则返回 true,否则返回 false。

instanceof作用: 判断object是不是class的子类
instanceof写法:左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

举例


package oop;
import oop.Demo06.Person;
import oop.Demo06.Student; 
import oop.Demo06.Teacher;


public class Application {
     
          Object k = new Student();
        //当前k定义为属于Object类,并且可执行student()结构的一个对象,即就是符合student类的对象。
        //Object > Person > Student
        System.out.println(k instanceof Student);//k和Student类有父子关系吗?是的。
        System.out.println(k instanceof Person);//k和Person类有父子关系吗?是的。
        System.out.println(k instanceof Object);//k和Object类有父子关系吗?是的。
        System.out.println(k instanceof Teacher);//k和Teacher类有父子关系吗?没有。
        System.out.println(k instanceof String);//k和String类有父子关系吗?没有。

        System.out.println("=================================>");

        Person y = new Student();
        //当前k定义为Person类,符合student()结构的对象,即就是符合student类的对象。
        //Object > Person > Student
        System.out.println(y instanceof Student);//k和Student类有父子关系吗?是的。
        System.out.println(y instanceof Person);//k和Person类有父子关系吗?是的。
        System.out.println(y instanceof Object);//k和Object类有父子关系吗?是的。
        System.out.println(y instanceof Teacher);//k和Teacher类有父子关系吗?没有,teacher和Student属于平级。
        //System.out.println(y instanceof String);//k和String类有父子关系吗?没有。

    }
}


package oop.Demo06;

public class Person {

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

}

package oop.Demo06;

public class Teacher extends Person{

}

package oop.Demo06;

public class Student extends Person{

    public void run(){
        System.out.println("student is running");
    }

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

}


运行结果

true
true
true
false
false
=================================>
true
true
true
false

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值