【java基础】-(一)面向对象特性之多态
1、定义:
多态(polymorphism)意为“一个名字,多种语义”。在程序设计语言中,多态性是指“一种定义,多种实现”.
2、优点:
语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
3、表现形式:
多态有两种表现形式:重载和覆盖
3.1、重载(overload)
是发生在同一类中。与什么父类子类、继承毫无关系。
标识一个函数除了函数名外,还有函数的参数(个数和类型)。也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同。
他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已!
3.2、覆盖(override)
是发生在子类中!也就是说必须有继承的情况下才有覆盖发生。
4、分类:
两种分法:面向对象,系统实现
4.1、系统实现多态
分为两种:编译时多态性、运行时多态性
4.2、面向对象多态
分为两种:通用多态和特定多态
两者的区别是前者对工作的类型不加限制,允许对不同类型的值执行相同的代码;后者只对有限数量的类型有效,而且对不同类型的值可能要执行不同的代码。
通用多态分为两种:参数多态(parametric)和包含多态(inclusion)
特定多态分为两种:过载多态(overloading)和强制多态(coercion)
强制多态排除了麻烦的类型和编译错误。重载多态像一块糖,允许程序员用相同的名字表示不同的方法,很方便。
5、分别阐述:
5.1、编译时多态性(静态联编)
对于多个同名方法,如果在编译时能够确定执行同名方法中的哪一个,则称为编译时多态性.
示例:
(1)
XXXX x1 = new XXXX(参数列表); //对象获得本类实例,对象与其引用的实例类型一致
XXX xx1 = new XXX(参数列表);
x1.toString(); //编译时多态性,执行XXX类的方法.
xx1.toString(); //编译时多态性,执行XXXX类覆盖的方法.
5.2、运行时多态性 (动态联编)
如果在编译时不能确定,只能在运行时才能确定执行多个同名方法中的哪一个,则称为运行时多态性.
示例:
(1)
XXXX为XXX的父类.
由于子类对象既是父类对象,父类对象与子类对象之间具有赋值相容性,父类对象能够被赋值为子类对象.例如,
XXXX x2 = new XXX(参数列表); //父类对象获得子类实例,子类对象即是父类对象
x2.toString(); //运行时多态
说明:
x2声明为父类对象却获得子类XXX的实例,那么x2.toString()究竟执行父类方法还是执行子类覆盖的方法呢?
这分为两种情况:
取决于子类是否覆盖父类方法.如果子类覆盖父类方法,则执行子类方法;
如果没有覆盖,则执行父类方法.
在编译时,仅仅依据对象所属的类,系统无法确定到底应该执行那个类的方法,只有运行时才能确定,因此这是运行时多态.
5.3、参数多态(parametric):
采用参数化模板,通过给出不同的类型参数,使得一个结构有多种类型。
示例:
(1)List抽象类
描述了一组具有同样特征的对象,提供了一个通用的模板。你可以通过指定一种类型以重 用这个抽象类。
这些参数可以是任何用户定义的类型,大量的用户可以使用这个抽象类,因此参数多态毫无疑问的成为最强大的多态。
5.4、过载多态:
也称重载多态,允许用相同的运算符或方法,去表示截然不同的意义。
虽然Java明确支持重 载,但不支持用户定义的操作符重载。
Java支持用户定义的函数重载。
5.5、强制多态:
编译程序通过语义操作,把操作对象的类型强行加以变换,以符合函数或操作符的要求。
基本类型的大多数操作符,在发生不同类型的数据进行混合运算时,编译程序一般都会进行强制多态
强制多态,即可是隐式的,也可显式转换。
示例:
(1)+ 的多态。int+double,编译系统一般会把int转换为double
(2)方法调用中的多态。
假设类Derived继承了类Base,类C有一个方法,原型为m(Base),在下面的代码中,编译器隐式的将 Derived类的对象derived转化为Base类的对象。
这种隐式的转换使m(Base)方法
使用所有能转换成Base类的所有参数。
C c = new C();
Derived derived = new Derived();
c.m( derived );
5.6、包含多态(不理解)
同样的操作可用于一个类型及其子类型。(注意是子类型,不是子类。)包含多态一般需要进行运行时的类型检查
主要是研究类族中定义与不同类中的同名函数的多态行为,主要是通过虚函数来实现。