【Java】面向对象的三大特性之一------多态

1.多态

1.1多态的产生

程序员在开发过程中,需要在代码中编写很多方法,其次,很多方法的形式差不多,那么到最后调用方法时就会很容易出错,

看下面的例子:

public class Test{
    int x;
    int y;
    int z;
    void print1(int x){
        System.out.println(x);
    }
    void print2(int x,int y){
        System.out.println(x+y);
    }
    void print3(int x,int y,int z){
        System.out.println(x+y+z);
    }

    public static void main(String[] args) {
        Test2 t=new Test2();
        t.print1(2);
        t.print2(2,3);
        t.print3(2,3,4);
    }
}

这时没有用多态表示的,如果参数更多的时候,那么当调用时,就会很容易出错的,所以,引入多态。

1.2多态(Polymorphism)

在设计一个方法时,通常希望该方法具有一定的通用性。例如要实现一个动物叫的方法,由于每种动物的叫声是不同的,因此可以在方法中接受一个动物类型的参数,当传入猫或者狗的时候,就会发出相对应的叫声。在同一个方法中,这种由于参数类型不同而导致执行效果各异的现象就是多态。

对上面的例子进行多态:

public class Test {
    int x;
    int y;
    int z;
    void print(int x){
        System.out.println(x);
    }
    void print(int x,int y){
        System.out.println(x+y);
    }
    void print(int x,int y,int z){
        System.out.println(x+y+z);
    }

    public static void main(String[] args) {
        Test2 t=new Test2();
        t.print(2);
        t.print(2,3);
        t.print(2,3,4);
    }
}

这个对基本数据类型进行了多态。

在java中为了实现多态,允许使用一个父类类型的变量来引用一个子类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果。

1.3 多态的核心表现

1.3.1 对象的多态性

(1)方法的重载:同一个方法名称根据参数类型或个数不同调用不同的方法体。

上例就是方法的重载,一般构造方法也会用到重载。

(2)方法的覆写:同一个父类的方法,可以根据实例化子类的不同也有不同的实现。

class Fanther{
    public void print(){
        System.out.println("父类方法");
    }
}
class Son extends Fanther{
    public void print(){
        System.out.println("子类方法");
    }
    public void print1(){
        System.out.println("子类的另一个方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Father f=new Son();
        f.print();
    }
}

1.3.2对象的多态性(前提:方法覆写)

(1)【自动,90%】对象的向上转型:父类 父类对象=子类实例;

class Fanther{
    public void print(){
        System.out.println("父类方法");
    }
}
class Son extends Fanther{
    public void print(){
        System.out.println("子类方法");
    }
    public void print1(){
        System.out.println("子类的另一个方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Father f=new Son();
        f.print();
    }
}

核心本质是:使用了哪一个子类(new 在哪里),而且调用的方法是否被子类覆写了

语句:Father f=new Son();他将父类对象句柄指向了子类对象,实际上操作的还是子类对象,只不过将对象句柄声明为父类的数据类型。f.print()由编译器根据实际情况选择了子类的print()函数。

看下面的例子:

class Fanther{
    public void print(){
        System.out.println("父类方法");
    }
}
class Son extends Fanther{
    public void print(){
        System.out.println("子类方法");
    }
    public void print1(){
        System.out.println("子类的另一个方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Father f=new Son();
        f.print1();
    }
}

这个程序没有通过编译,因为f是父类的数据类型,而在父类中没有print1()方法,只有print()方法,又由于这个句柄指向子类句柄,所以只能操作子类中覆盖父类的方法。如果父类引用指向一个子类的对象,那么通过父类引用,只能调用父类所定义的允许继承的方法,如果子类重写了继承父类的方法,那么会调用子类中的方法。

(2)【强制,1%】对象的的向下转型,子类 子类对象=(子类)父类实例

class Fanther{
    public void print(){
        System.out.println("父类方法");
    }
}
class Son extends Fanther{
    public void print(){
        System.out.println("子类方法");
    }
    public void print1(){
        System.out.println("子类的另一个方法");
    }
}
public class Test {
    public static void main(String[] args) {
         Father f=new Son();
        f.print();
        Son s=(Son) f;
        s.print1();
        
    }
}

【此概念一般不用】,如果想要进行向下转型,一定要先实现向上转型。                                                                                          再看一个例子:

     

class Person{
    public void print(){
        System.out.println("1.父类方法");
    }
}
class Child extends Person{
    public void print(){
        System.out.println("2.子类方法");
    }
    public void print1(){
        System.out.println("3.子类的另一个方法");
    }
}
class Yong extends Person{
    public void print(){
        System.out.println("4.子类方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Yong yong=new Yong();
        personPrint(yong);
    }
    public static void personPrint(Person person){
        Child child=(Child)person;
        child.print();
        child.print1();
    }
}

      这个在运行时显示错误,Yong 类型不能转换成Child类型,强制类型转换时,Person类型无法转换为Child类型。

所以,java中提供了一个instanceof,它可以判断一个对象是否为某个类(或接口)的实例或者子类实例。

语法格式:对象(或者对象引用变量)instanceof  类 (或接口)

     

class Person{
    public void print(){
        System.out.println("1.父类方法");
    }
}
class Child extends Person{
    public void print(){
        System.out.println("2.子类方法");
    }

}
class Yong extends Person{
    public void print(){
        System.out.println("4.子类方法");
    }
}
public class Test4 {
    public static void main(String[] args) {
        Yong yong=new Yong();
        personPrint(yong);
    }
    public static void personPrint(Person person){
        if(person instanceof Child){
            Child child=(Child)person;
            child.print();
           // child.print1();
        }
        else{
            System.out.println("这个人不是孩子 ");
        }
    }
}

           

对象的向上转型有一个最核心的用途:操作参数统一。

总结:

  • 对象多态性的核心在于方法的覆写;
  • 通过对象的向上转型可以实现参数的统一,向下转型可以实现子类扩充方法,一般不操作向下转型(有安全隐患)。
  • 两个没有关系的类对象是不能进行转型的,一定会产生ClassCastException.                         
发布了62 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43669007/article/details/102555374