您好,欢迎来到二三四教育网。
搜索
您的当前位置:首页Java基础——多态

Java基础——多态

来源:二三四教育网


提示:以下是本篇文章正文内容,下面案例可供参考

一、java多态是什么?

1.概念:

在java的面向对象中,多态则是指同一个行为可以有多个不同表现形式的能力。也就是说,在父类中定义的属性和方法,在子类继承后,可以有不同的数据类型或表现出不同的行为。这可以使得同一个属性或方法,在父类及其各个子类中,可能会有不同的表现或含义。

例如:龙生九子,每子行为和外貌上不相同。

2. 必要条件

我们要想实现多态,需要满足3个必要条件:

● 继承:多态发生在继承关系中,必须存在有继承关系的父类和子类中,多态建立在封装和继承的基础之上;

● 重写:必须要有方法的重写,子类对父类的某些方法重新定义;

● 向上转型:就是要将父类引用指向子类对象,只有这样该引用才既能调用父类的方法,又能调用子类的方法。

只有满足了以上3个条件才能实现多态,开发人员也才能在同一个继承结构中,使用统一的代码实现来处理不同的对象,从而执行不同的行为。

3. 实现方式

在Java中,多态的实现有如下几种方式:

方法重载:重载可以根据实际参数的数据类型、个数和次序,在编译时确定执行重载方法中的哪一个。

方法重写:这种方式是基于方法重写来实现的多态;

接口实现:接口是一种无法被实例化但可以被实现的抽象类型,是对抽象方法的集合。定义一个接口可以有多个实现,这也是多态的一种实现形式,与继承中方法的重写类似。

二、使用步骤

1.Java中的多态,分为编译时多态和运行时多态。

一句话,如果我们在编译时就能确定要执行的方法属于哪个对象、执行的是哪个方法,这就是编译时多态,否则就是运行时多态!

  • 编译时取决于父类,运行时取决于子类。

2.运行下的多态

代码如下(示例):

/**
 * 定义一个“圆形”接口————————父类
 */
public interface Shape {
    //绘制方法,接口中的方法一般没有实现,需要子类去实现
    void draw();
}

分别定义其实现类——圆形

/**
 * 实现Shape接口,并对接口中的方法进行实现——“圆形”类
 */
public class Circle implements Shape{
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }

    //当父类引用指向子类对象时,父类只能调用执行那些在父类中声明,被子类覆盖的子类方法,不能执行子类独有的
    public void scroll(){
        System.out.println("圆形类独有的方法"); //子类独有的方法
    }
}

分别定义其实现类——矩形

/**
 * 实现Shape接口,并对接口中的方法进行实现————“矩形”类
 */
public class Traingle implements Shape{
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}

分别定义其实现类——三角形

/**
 * 实现Shape接口,并对接口中的方法进行实现————“三角形”类
 */
public class Square implements Shape{
    @Override
    public void draw() {
        System.out.println("绘制三角形");
    }
}

父子关系确定好之后,接下来我们再定义一个额外的测试类。在这个测试类中,我们创建出以上三个图形对象。注意,在=等号左侧,变量的类型都是Shape父类;=等号右侧,变量的值是具体的子类!这种变量的定义过程,其实就是符合了多态的第三个必要条件,也就是所谓的”向上转型,父类引用指向子类对象“。

/**
 - 注意,在=等号左侧,变量的类型都是Shape父类;=等号右侧,变量的值是具体的子类!
 - 这种变量的定义过程,其实就是符合了多态的第三个必要条件,也就是所谓的”向上转型,父类引用指向子类对象“
 */
public class ShapeTest {
    public static void main(String[] args) {
        //多态测试
        Shape shape01=new Circle();
        shape01.draw();

        Shape shape02=new Traingle();
        shape02.draw();

        Shape shape03=new Square();
        shape03.draw();
    }
}

3.多态——运行的结论:
Java实例方法的调用,是基于运行时实际类型的动态调用,而非声明的变量类型!通俗地说,就是我们调用的到底是哪个对象的方法,不是由=号左侧声明的引用变量来决定的,而是由=号右侧的实际对象类型来决定的!

2.编译下的多态

  • 父类
/**
 * 编译时多态——定义父类
 */
public class Father {
    //父类中的成员变量
    String name="老子";

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

    //父类中的静态方法——静态方法不能重新被重写,只会被子类隐藏
    public static void play(){
        System.out.println("父亲玩球");
    }
}
  • 子类
/**
 * 编译时多态
 */
public class Son extends Father{

    //当子类与父类的类型和名称相同时,父类的被隐藏
    String name="儿子";

    int age=12;

    @Override
    public void eat() {
        //方法重写时,子类可以对父类的同名方法进行扩展,方法体的内容也可以跟父类的不一样
        System.out.println("儿子吃肉");
    }

    public void drink(){
        System.out.println("儿子喝水");
    }

    //子类中与父类同名的静态方法,这不是重写,而是子类对父类同名静态方法的隐藏
    public static void play(){
        System.out.println("儿子玩火");
    }

    public static void main(String[] args) {
        //创建父类对象
//        Father father=new Father();
//        father.eat();

        //创建子类对象
//        Son son=new Son();
//        son.eat();

        //当前面引用与后面的实例类型不一致的时候,且子类和父类有共同属性的时候,父类会调用自己的先
        Father son=new Son();
        System.out.println("name="+son.name);
        son.play();
    }
}

根据上述代码的执行结果可知,当父类引用指向子类对象时,父类只能调用执行那些在父类中声明、被子类覆盖的子类方法,而不能执行子类独有的成员方法。否则在编译阶段就会出现”The method drink() is undefined for the type Father“异常。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- how234.cn 版权所有 赣ICP备2023008801号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务