前言:

书接上回,继承性体现了类与类之间的层次关系。本章我们在掌握继承的基础上,深入地学习一下面向对象的多态性。

多态性是面向对象思想中的重中之重!对于初学者来说,不仅理解起来比较费劲,应用上更是捉襟见肘。

但多态性的应用,在我们日常开发过程中,可以说随处可见,是各种框架的灵魂知识点之一,是三大特性中最重要的特性,没有之一,所以必须认真掌握。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(1)

那么多态性的概念是什么呢?

多态性统筹的理解,指的是同一种行为,具有不同的表现形式。

多态性从应用上分成两大类:静态多态性,动态多态性。

静态多态性:

静态多态性又称编译期多态性,在程序被编译的时候,就确定类的对象与函数的调用关系,主要体现在方法重载、运算符重载。

动态多态性:

动态多态性又称运行时多态性,在程序运行期间,根据传入的对象不同,决定调用的是哪个对象的函数,主要体现在方法重写!

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(2)

静态多态性对于大家来说,应该耳熟能详了,接下来我们主要学习下,动态多态性的相关知识体系。

动态多态性地实现基础,就是对象之间的转型。在面向对象编程语言中,数据类型的转换方式有三种:

1.值类型的相互转换,转换规则:按取值范围。

2.值类型与引用类型之间的转换,转换规则:装箱与拆箱。

3.引用类型之间的转换,转换规则:建立在继承的基础上。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(3)

对象之间的类型转换,我们注意三个要素:

1.必须建立在继承的基础上,例如A、B、C三个类,B继承于A,C为独立的类,那么在路上相遇,A可以让B叫爸爸,但不能让C叫爸爸,这样会挨揍的!因为A与C是属于陌生人的存在。

2.向上转型:父类引用指向子类对象,属于自动、隐式转换,例如:A a = new B();儿子听老子的话,属于天经地义的事。

3.向下转型:必须建立在向上转型的基础上,属于强制转换,因为你想说服你的父辈,总是很艰难的,需要使用一些非常手段,比如躺地上耍赖[吐舌]。也就是说,如果你希望实现向下转型的操作,那么前提是发生了一次向上转型操作。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(4)

例如:A a = new B();这属于父类指向子类,或者将子类对象赋值给父类,属于向上转型。我们可以在这个基础上,B b = (B)a;来实现向下转型的操作,通过这种方式,来回归自我。

例如:A a = new A();在这个基础上,B b = (B)a;这种方式是完全错误的!因为向下转型,没有建立在向上转型的基础上。

总结一下:

父类指向子类,那么就是子类向上转型操作,用周杰伦的话,就是听妈妈的话!如果子类指向父类的对象,则是父类要向子类向下转型,需要强制的类型转换。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(5)

看了这么多,接下来搞一题,让我们热乎热乎身子。两个类A、B的故事,A是父类,B继承了A,A中有一个字段x,B中有一个字段y,就是这么简单的结构,就是这么简单的题目。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(6)

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(7)

那么A类指向自己的子类B,A的对象能够访问字段x,还是字段y,或者x、y都可以访问呢?

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(8)

答案估计与你想得不太一样,A类的对象a,可以访问的变量竟是自己的字段x!

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(9)

怎么样,多态性的邪恶一面逐渐展现,让很多小伙伴们摸不清头脑。没关系,再坚持一下,离放弃很近了[泣不成声],我们来分析一波,就真相大白了!

引用类型的创建,可以拥有两个类型,一个是编译类型,一个是运行时类型。

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

运行时的类型:由该变量指向的对象类型决定。

当变量的编译时类型和运行时类型不一致时,通过变量访问它所引用的对象的实例时,该实例变量的值由声明该变量的类型决定。

例如:A a = new B();等号左边的A为编译时类型,等号右边的B为运行时类型。所以访问的内容范围,是由编译器类型A决定的,所以这就是为什么A可以访问自己类中的成员变量,无法访问B类中定义内容的原因所在。

当编译时类型和运行时类型不一致,就会出现多态性。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(10)

接下来我们学习下,实现面向对象多态性编程的三个步骤(三个步骤缺一不可):

1.建立继承关系,无兄弟,不篮球。无继承,不多态。

2.子类重写父类的方法,多态性指的是行为的多样化,同样的行为,对于不同的对象有着不同的实现方式。

例如:你爷爷吃饭喜欢吃肉,你爹吃饭喜欢吃菜,你姑喜欢吃面条,而你却钟爱螺蛳粉。一种吃的行为,对于不同的子类有着不同的实现方式。

3.父类型指向子类型(向上转型),一般将父类型作为方法的参数,或者方法的返回值。

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(11)

我们学习了多态性的概念,基础知识体系,以及编程方式。接下来看看多态性的好处是什么?为什么在编程过程中,需要频繁地使用该特性。

在这里用一个案例,可以充分地说明,多态性在编程上的优势所在!比如:动物园有若干动物,狗、猫、骆驼,还有饲养员。

那么对于饲养员来说,喂动物是一个方法,如果为每个动物定义一个喂食的方法,程序实在太冗余了,而且缺乏扩展性,如果动物园引进新的动物,我们难道还要继续编写新的方法?这肯定不是明智之举。

所以我们采用多态性的特点,将动物抽象成一个父类,分别继承这个父类,以父类作为参数的入口,既可以简化方法的定义,又可以实现程序的功能,何乐而不为呢?

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(12)

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(13)

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(14)

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(15)

简单介绍面向对象中的多态性概念(面向对象编程三大特性之多态性)(16)

总结一下:

无论静态多态性,方法重载。还是动态多态性,方法重写!本质解决的问题,都是简化了方法的定义,避免方法定义的冗余性。

通过这样的原理,写出的程序,更有健壮性,扩展性也更好!

,