Polymorphism

多态

多态意味着父类型的变量可以引用子类型的对象

基类型对象访问派生类重写的方法;循环调用基类对象,访问不同派生类;——滕国栋

首先明确一下两个概念:向上转型和向下转型

向上转型

human 是 man 的基类

man a = new man()
b = new human()
a = b

向下转型

human b = new human()
man a = new man()
b = a

继承关系使一个子类能继承父类的特征,并且附加一些新特征。子类是它的父类的特殊化,每个子类的实例都是其父类的实例,但是反过来不成立。例如:每个圆都是一个几何对象,但并非每个几何对象都是圆。因此,总可以将子类的实例传给需要父类型的参数。考虑以下程序中的代码。

public class PolymorphismDemo {
    public static void main(String[] args) {
        displayObject(new Circle(1, "red", false));
        displayObject(new Rectangle(1, 1, "black", true));
    }
    //Circle,Rectangle都是GeometricObject的子类
    public static void displayObject(GeometricObject object) {
        System.out.println("Create on " + object.getDateCreated() + ". Color is " + object.getcolor());
    }
}

// 运行结果
// Create on Fri Nov 26 15:46:30 CST 2021. Color is red
// Create on Fri Nov 26 15:46:30 CST 2021. Color is black

方法displayobject 具有Geometricobject类型的参数。可以通过传递任何一个Geometricobject的实例(例如:在new Circle(1,“red”, false)和new Rectangle(1,1,“black”,true))来调用displayobject,使用父类对象的地方都可以使用子类的对象。这就是通常所说的多态( polymorphism,它源于希腊文字,意思是“多种形式")。简单来说,多态意味着父类型的变量可以引用子类型的对象。

如果子类和父类都有相同的方法,例如

Object o = new GeometricObject();
System.out.println(o.toString());

如何决定运行时调用哪个方法

动态绑定

调用哪个toString()呢?为了回答这个问题,我们首先介绍两个术语:声明类型和实际类型。一个变量必须被声明为某种类型。变量的这个类型称为它的声明类型( declared type)。这里, 。的声明类型是object,一个引用类型变量可以是一个nul1值或者是一个对声明类型实例的引用。实例可以使用声明类型或它的子类型的构造方法创建。变量的实际类型(actual type)是被变量引用的对象的实际类。这里, 。的实际类型是Geometricobject,因为。引用使用new Geometricobject()创建的对象。。调用哪个. toString()方法由。的实际类型决定。这称为动态绑定(dynamic binding)。动态绑定工作机制如下:假设对象。是类C, c2, …, Ca.1, C,的实例,其中C,是C2的子类, C,是C的子类, …, Cn.1是C,的子类,如图11-2所示。也就是说, C,是最通用的类,C,是最特殊的类。在Java中, G,是object类。如果对象。调用一个方法p,那么JVM会依次在类C, C2, …, Cni1, C,中查找方法p的实现,直到找到为止。一旦找到一个实现,就停止查找,然后调用这个首先找到的实现。以下给出一个演示动态绑定的例子。

public class DynamicBindingDemo {
    public static void main(String[] args) {
        m(new GraduateStudent());
        m(new Student());
        m(new Person());
        m(new Object());
    }

    public static void m(Object x) {
        System.out.println(x.toString());
    }
}

class GraduateStudent extends Student {
}

class Student extends Person {
    @Override
    public String toString() {
        return "Student";
    }
}

class Person extends Object {
    @Override
    public String toString() {
        return "Person";
    }
}

// 运行结果:
// Student
// Student
// Person
// java.lang.Object@2d363fb3

方法m 有一个object类型的参数。可以用任何对象(例如:new GraduateStudent()、 new Student()、 new Person()和new object())作为参数来调用m方法。当执行方法m(object x)时,调用参数x的tostring方法。x可能是GraduateStudentStudent, Person或者object的实例。类Student, Person以及Object都有它们自己对toString方法的实现。使用哪个实现取决于运行时×的实际类型。调用m(new GraduateStudent())会导致定义在Student类中的toString方法被调用调用m(new Student())会调用在Student类中定义的toString方法。调用m(new Person())会调用在Person类中定义的toString方法。调用m(nenobject()) 会调用在object类中定义的toString方法。匹配方法的签名和绑定方法的实现是两个不同的问题。引用变量的声明类型决定了编译时匹配哪个方法。在编译时,编译器会根据参数类型、参数个数和参数顺序找到匹配的方法。一个方法可能在沿着继承链的多个类中实现。Java虚拟机在运行时动态绑定方法的实现, 这是由变量的实际类型决定的。

操作符instanceof

考虑一下代码:

void someMethod(Object myObject){
    if (myObject instanceof Circcle){
        System.out.println("The circle diameter is " + 
        ((Circle)myObject).getDiameter());
    }
}

你可能会奇怪为什么必须进行类型转换。变量myobject被声明为object。声明类型决定了在编译时匹配哪个方法。使用myobject. getDiameter()会引起一个编译错误,因为object类没有getoiameter方法。编译器无法找到和myobject.getDiameter()匹配的方法。·所以,有必要将myobject转换成Circle类型,以告诉编译器myobject也是Circle的一个实例。为什么不在一开始就把myobject定义为Circle类型呢?为了能够进行通用程序设计一个好的做法是把变量定义为父类型,这样,它就可以接收任何子类型的对象。

总结

1.多态现实意义理解:

现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

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

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

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

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

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

5.动态绑定

JVM在o的子类中找到第一要求的方法名就对他经行操作

6. 操作符instanceof

用于判断类型转换后的对象是否为判断对象

7.理解:

多态是同一个行为具有多个不同表现形式或形态的能力。

多态就是同一个接口,使用不同的实例而执行不同操作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值