java多态
java多态练习题

java多态练习题Java多态练习题Java是一种面向对象的编程语言,其中的多态性是其最重要的特性之一。
通过多态,我们可以实现代码的灵活性和可扩展性。
在这篇文章中,我们将通过一些练习题来加深对Java多态性的理解。
练习一:动物的多态假设有一个动物类Animal,它有一个方法叫做makeSound(),用于输出动物的叫声。
现在我们派生出了两个子类Dog和Cat,它们分别重写了makeSound()方法,分别输出"汪汪汪"和"喵喵喵"。
现在我们创建一个Animal类型的数组,数组中存放了不同的动物对象,包括Dog和Cat。
我们遍历数组,调用每个动物对象的makeSound()方法,观察输出结果。
代码示例:```javaclass Animal {public void makeSound() {System.out.println("动物发出叫声");}}class Dog extends Animal {@Overridepublic void makeSound() {System.out.println("汪汪汪");}}class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("喵喵喵");}}public class PolymorphismExample {public static void main(String[] args) { Animal[] animals = new Animal[3]; animals[0] = new Dog();animals[1] = new Cat();animals[2] = new Dog();for (Animal animal : animals) {animal.makeSound();}}}```运行结果:```汪汪汪喵喵喵汪汪汪```通过这个练习题,我们可以看到多态的作用。
Java基本概念:多态

Java基本概念:多态⼀、简介描述:多态性是⾯向对象编程中的⼀个重要特性,主要是⽤来实现动态联编的。
换句话说,就是程序的最终状态只有在执⾏过程中才被决定,⽽⾮在编译期间就决定了。
这对于⼤型系统来说能提⾼系统的灵活性和扩展性。
多态允许相同类域的不同对象对同⼀消息做出响应。
即同⼀消息可以根据发送对象的不同⽽采⽤多种不同的⾏为⽅式。
多态可以让我们不⽤关⼼某个对象到底是什么具体类型,就可以使⽤该对象的某些⽅法,从⽽实现更加灵活的编程,提⾼系统的可扩展性。
如果对象的编译时类型和运⾏时类型不⼀致,就会造成多态。
存在条件:1. 类之间有继承关系。
2. ⼦类重写⽗类⽅法。
3. ⽗类引⽤指向⼦类对象。
注意:多态是⽅法的多态,属性没有多态性。
⼀个对象的实际类型是确定的,但是可以指向这个对象的引⽤的类型,却是可以是这对象实际类型的任意⽗类型。
⼦类继承⽗类,调⽤⽅法,如果该⽅法在⼦类中没有重写,那么就是调⽤的是⼦类继承⽗类的⽅法,如果重写了,那么调⽤的就是重写之后的⽅法。
'protected'修饰的⽗类⽅法可以被⼦类见到,也可以被⼦类重写,但是它是⽆法被外部所引⽤的,所以没有多态性。
通过⼀个变量调⽤其引⽤的对象的⼀个⽅法,编译器是否能让其编译通过,主要是看该变量类型的类中有没有定义该⽅法,如果有则编译通过,如果没有则编译报错。
⽽不是看这个变量所引⽤的对象中有没有该⽅法。
Java中的⽅法调⽤,是运⾏时动态和对象绑定的,不到运⾏的时候,是不知道到底哪个⽅法被调⽤的。
编写程序时,如果想调⽤运⾏时类型的⽅法,只能进⾏类型转换,不然通不过编译器的检查。
但是如果两个没有关联的类进⾏强制转换,会报类型转换异常:ClassCastException。
⽰例:public class Test {public static void main(String[] args) {/* 编译看左,运⾏看右 */Student student = new Student();/* 变量person是可以指向Person类型或其⼦类型的对象,所以可以指向Student类型对象 */Person person = new Student();/* 变量student能调⽤的⽅法是Student类中有的⽅法(包括继承过来的) */student.say();//Student/* 变量person能调⽤的⽅法是Person类中有的⽅法 */person.say();//Student}}class Person {public void say() {System.out.println("Person");}}class Student extends Person {public void say() {System.out.println("Student");}}⼆、重写、重载、多态的关系1. 重载是编译时多态调⽤重载的⽅法,在编译期间就要确定调⽤的⽅法是谁,如果不能确定则编译报错。
在JAVA中有两种多态指的是什么

同问 在JAVA中有两种多态指的是什么 2009-01-15 14:32 提问者: mdydyy |浏览次数:2218次
我来帮他解答
精彩回答
2009-01-15 15:11在JAVA中有两种多态是指:运行时多态和编译时多态。关于类的多态性简介如下: 多态(polymorphism)意为一个名字可具有多种语义.在程序设计语言中,多态性是指”一种定义,多种实现”.例如,运算符+有多种含义,究竟执行哪种运算取决于参加运算的操作数类型: 1+2 //加法运算符 “1” + “2” //字符串连接运算,操作数是字符串 多态性是面向对象的核心特征之一,类的多态性提供类中成员设计的灵活性和方法执行的多样性. 1、类多态性表现 (1)方法重载 重载表现为同一个类中方法的多态性.一个类生命多个重载方法就是为一种功能提供多种实现.编译时,根据方法实际参数的数据类型\个数和次序,决定究竟应该执行重载方法中的哪一个. (2)子类重定义从父类继承来的成员 当子类从父类继承来的成员不适合子类时,子类不能删除它们,但可以重定义它们,使弗雷成员适应子类的新需求.子类重定义父类成员,同名成员在父类与子类之间表现出多态性,父类对象引用父类成员,子类对象引用子类成员,不会产生冲突和混乱. 子类可重定义父类的同名成员变量,称子类隐藏父类成员变量.子类也可以重定义父类的同名成员方法,当子类方法的参数列表与父类方法参数列表完全相同时,称为子类方法覆盖(override)父类方法。覆盖父类方法时,子类方法的访问权限不能小于父类方法的权限。 由于Object类的equals()方法比较两个对象的引用是否相等而不是值是否相等,因此一个类要覆盖Object类的equals()方法,提供本类两个对象比较相等方法. 覆盖表现为父类与子类之间方法的多态性.java 寻找执行方法的原则是:从对象所属的类开始,寻找匹配的方法执行,如果当前类中没有匹配的方法,则逐层向上依次在父类或祖先类中寻找匹配方法,直到Object类. 2、super 引用 在子类的成员方法中,可以使用代词super引用父类成员.super引用的语法如下: super([参数列表]) //在子类的构造方法体中,调用父类的构造方法 super.成员变量 //当子类隐藏父类成员变量时,引用父类同名成员变量 super.成员方法([参数列表]) //当子类覆盖父类成员方法时,调用父类同名成员方法 *注意:super引用没有单独使用的语法 3、多态性有两种: 1)编译时多态性 对于多个同名方法,如果在编译时能够确定执行同名方法中的哪一个,则称为编译时多态性. 2)运行时多态性 如果在编译时不能确定,只能在运行时才能确定执行多个同名方法中的哪一个,则称为运行时多态性. 方法覆盖表现出两种多态性,当对象获得本类实例时,为编译时多态性,否则为运行时多态性,例如: XXXX x1 = new XXXX(参数列表); //对象获得本类实例,对象与其引用的实例类型一致 XXX xx1 = new XXX(参数列表); x1.toString(); //编译时多态性,执行XXX类的方法. xx1.toString(); //编译时多态性,执行XXXX类覆盖的方法. XXXX为XXX的父类. 由于子类对象既是父类对象,父类对象与子类对象之间具有赋值相容性,父类对象能够被赋值为子类对象.例如, XXXX x2 = new XXX(参数列表); //父类对象获得子类实例,子类对象即是父类对象 x2.toString(); //运行时多态 x2声明为父类对象却获得子类XXX的实例,那么x2.toString()究竟执行父类方法还是执行子类覆盖的方法呢? 这分为两种情况: 取决于子类是否覆盖父类方法.如果子类覆盖父类方法,则执行子类方法; 如果没有覆盖,则执行父类方法. 在编译时,仅仅依据对象所属的类,系统无法确定到底应该执行那个类的方法,只有运行时才能确定,因此这是运行时多态. 父类对象并不能执行所有的子类方法,只能执行那些父类中声明\子类覆盖的子类方法.
java多态演讲ppt

sram实现多态三个条件:
1:继承 2:重写(重写父类继承的方法) 3:父类引用指向字类对象
sramwww.
安博思软
多态的实现:通过继承实现
JAVA中,一个类之能有一个父类,不能多继承。一个父类可 以有多个子类,而在子类里可以重写父类的方法,这样每个子
sramwww.
安博思软
sramwww.
安博思软
多态性有两种:
编译时多态性(静态绑 定)
运行时多态性(动态 绑定)
如果在编译时不能确定,只能 , 在运行时才能确定执行多个 同名方法中的哪一个,则称为 运行时多态性。
对于多个同名方法,如果在编 译时能够确定执行同名方法 中的哪一个,则称为编译时多 态性。
sramwww.
安博思软
多态的实现:通过接口实现
继承 单继承 一个类只能继承一个父类! 一个类只能继承一个父类!
接口
多实现
一个类可以同时实现多个接口! 类可以同时实现多个接口! 同时实现多个接口
一个接口类型变量也可以指向其实现类的实例,这也是 个接口类型变量也可以指向其实现类的实例,这也是
输出结果:
我知道错了,别打了! 为什么打我?我做错什么了! 我跑,你打不着!
//子类3 public class Son3 extends Father{ //重写父类打孩子方法 public void hitChild(){ System.out.println("我跑,你打不着!"); }}
//子类1 public class Son1 extends Father{ //重写父类打孩子方法 public void hitChild(){ System.out.println("我知道错了,别打了!"); }}
JAVA多态性 ppt课件

a.fun1();
// 此方法被子类覆写过
}
}
PPT课件
6
对象的向下转型
class A{ public void fun1(){
// 定义类A // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
} public void fun2(){
PPT课件
5
对象的向上转型
class A{ public void fun1(){
// 定义类A // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
} public void fun2(){
// 定义fun2()方法
this.fun1() ;
A a = new B() ;
// 发生了向上转型的关系,子类 --> 父类
B b = (B)a ;
// 此时发生了向下转型关系
b.fun1() ;
// 调用方法被覆写的方法
b.fun2() ;
// 调用父类的方法
b.fun3() ;
// 调用子类自己定义的方法
}
}
PPT课件
7
多态禁忌
•千万不要出现这样的操作:就是将父类对象转换成为子类是类型 – Animal a=new Animal(); – Dog d4=(Dog)a;//类造型异常
}
}; class B extends A{
public void fun1(){
// 子类通过extends继承父类 // 覆写父类中的fun1()方法
java 多态笔试题

当然,我可以给你提供一些关于Java多态的笔试题。
请注意,以下问题仅供参考。
1. 什么是Java中的多态性?
2. 如何实现多态性?
3. 什么是动态绑定(Dynamic Binding)?
4. Java中的重写(Overriding)和重载(Overloading)的区别是什么?
5. 简要解释一下抽象类和接口的作用,并比较它们之间的异同点。
6. 能否在Java中创建一个抽象类的实例?为什么?
7. 是否可以同时使用final和abstract关键字修饰一个类或方法?为什么?
8. 什么是向上转型(Upcasting)和向下转型(Downcasting)?它们在多态中的作用是什么?
9. 请解释一下Java中的instanceof关键字的作用和用法。
10. 在Java中如何实现方法的重载?
这些问题应该可以帮助你巩固对Java多态的理解。
请记住,理论知识和实际编程经验相结合是非常重要的。
祝你好运!如果你有其他问题,请随时提问。
java的封装,继承和多态(思维导图)
java的封装,继承和多态类和对象类类声明 { 成员变量的声明; 成员方法的声明及实现; }声明类:[修饰符] class 类<泛型> [extends 父类] [implements 接口列表]声明成员变量:[修饰符]数据类型 变量[=表达式]{,变量[=表达式]}成员方法声明:[修饰符]返回值类型 方法([形式参数列表])[throws 异常类列表]{语句序列;[return[返回值]]; }重载:一个类中可以有多个同名的成员方法,前提是参数列表不同,称为类的成员方法重载,重载的多个方法为一种功能提供多种实现。
重载方法之间必须以不同的参数列表(数据类型、参数个数、参数次序)来区别。
例如,MyDate 类可声明多个重载的set()方法如下: void set(int y,int m, int d)void set(int m, int d) //重载方法,参数个数不同void set(int d) void set(MyDate date)//重载方法,参数的数据类型不同对象对象声明:类 对象构造实例:对象 = new 类的构造方法([实际参数列表])引用对象的成员变量和调用成员方法:对象.成员变量 对象.成员方法([实际参数列表])类的封装性构造与析构类的构造方法用于创建类的一个实例并对实例的成员变量进行初始化一个类可声明多个构造方法对成员变量进行不同需求的初始化,构造方法不需要写返回值类型,因为它返回的就是该类的一个实例。
例:MyDate类声明以下构造方法:public MyDate(int year, int month, int day)// 声明构造方法,方法名同类名,初始化成员变量 {set(year, month day);// 调用 set()方法,为成员变量赋值}使用new运算符调用指定类的构造方法,实际参数列表必须符合构造方法声明。
例如:MyDate d1 = new MyDate(2017,10,1);//创建实例并初始化成员变量当一个类没有声明构造方法时,Java 自动为该类提供一个无参数的默认构造方法对象的引用与运算this引用访问本类的成员变量和成员方法:this.成员变量,this.成员方法([实际参数列表])调用本类重载的构造方法:this([实际参数列表])访问控制类的访问控制权限公有和(public)和缺省类中成员4级访问控制权限及范围声明set()和get()方法存取对象的属性例:public void set(int year, int month, int day) //设置日期值 public void set(MyDate date)//设置日期值,重载 public int getYear()//获得年份 public int getMonth()// 获得月份 public int getDay()//获得当月日期静态成员定义及访问格式使用关键字static声明的成员称为静态成员在类内部,可直接访问静态成员,省略类名。
java语言的四大特点是什么
封装、继承、多态、抽象是java语言的四大特点,Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
java语言的热点1、封装:封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。
采用封装的思想保证了类内部数据结构的完整性,应用该类的用户不能轻易地直接操作此数据结构,只能执行公开的数据。
这样避免了外部操作对内部数据的影响,提高了程序的可维护性。
2、继承:类与类之间同样具有关系,如一个百货公司与销售员类相互联系,类之间的这种关系被称为关联。
两个类之间的关系有很多种,继承是关联的一种。
继承就是指子类继承了父类的属性和行为。
例如鸽子类保留了鸟类的属性和行为,这样就节省了定义鸟和鸽子共同具有的属性和行为时间,这就是继承的基本思想。
3、多态:多态就是指同一种事物在不同的情况下的多种表现形式,多态其实就是将父类对象应用于子类的特征。
就图形类来说,每个图形都拥有自己的能力,这个能力可以看作是该类具有的行为,如果将子类的对象统一看作是父类的实例对象,当我们绘制图形时,简单的调用父类也就是图形类绘制图形的方法即可绘制任何图形,这就是多态的基本思想。
4、抽象:抽象是指不能某一类对象使用具体的语言进行描述。
例如对于图形对象不能使用具体的语言进行描述,它有几条边,它是什么图形,这种类通常被定义为抽象类。
抽象只对对象的行为和属性进行改变,不在乎方法的细节。
java的发展前景作为一种最火的网络编程语言之一,Java语言在当今信息化社会中发挥了重要的作用。
随着网络的迅速发展,Web应用日益广泛,Java语言也得到了快速的发展,权威统计机构统计,在所有软件开发类人才的需求中,对Java工程师的需求达到全部需求量的60%~70%,未来的就业前景非常好。
Java软件工程师一般月薪范围在6000-10000元,远远超过了应届毕业生月薪2500元的平均水平。
《java面向对象程序设计继承和多态》教案
《Java面向对象程序设计-继承和多态》教案第一章:引言1.1 课程简介本课程旨在帮助学生掌握Java面向对象程序设计中的继承和多态概念。
通过学习,学生将能够理解继承和多态的原理,并能够运用它们解决实际编程问题。
1.2 课程目标理解继承的概念和原理掌握如何使用继承来实现代码复用理解多态的概念和原理掌握如何使用多态来实现动态绑定第二章:继承2.1 继承的概念介绍继承的定义和作用解释为什么使用继承2.2 继承的语法介绍如何使用extends关键字实现继承解释继承中的构造函数和继承关系2.3 继承的实现演示如何使用继承来复用代码解释继承的层次结构和菱形继承第三章:多态3.1 多态的概念介绍多态的定义和作用解释多态的好处3.2 方法重写解释方法重写的概念和规则演示如何使用方法重写来实现多态3.3 方法重载解释方法重载的概念和规则演示如何使用方法重载来提高代码可读性第四章:继承和多态的案例分析4.1 案例一:动物和鸟类使用继承和多态来定义动物和鸟类的关系实现动物和鸟类的属性和方法4.2 案例二:形状和圆形使用继承和多态来定义形状和圆形的关系实现形状和圆形的属性和方法第五章:总结和练习5.1 课程总结回顾继承和多态的概念和原理强调继承和多态在面向对象程序设计中的重要性5.2 练习题提供一些练习题,以帮助学生巩固所学知识第六章:继承和多态的深入理解6.1 继承的类型解释接口继承和类继承的区别讨论继承的优点和缺点6.2 多态的应用探讨多态在日常编程中的应用场景分析多态如何提高程序的可扩展性和灵活性第七章:Java中的继承和多态实例7.1 继承实例:汽车和摩托车通过实例展示如何使用继承来创建汽车和摩托车类演示如何通过继承来扩展属性和方法7.2 多态实例:支付接口和具体的支付方式创建一个支付接口和多个具体的支付方式类演示如何使用多态来实现不同的支付方法第八章:继承和多态的陷阱与最佳实践8.1 继承的陷阱讨论继承可能带来的过度耦合问题解释如何避免继承的陷阱8.2 多态的陷阱分析多态可能导致的类型不匹配问题探讨如何安全地使用多态8.3 最佳实践提供使用继承和多态的最佳实践指南强调代码可读性和可维护性第九章:继承和多态在设计模式中的应用9.1 设计模式简介介绍设计模式的概念和重要性解释设计模式与继承和多态的关系9.2 继承和多态在设计模式中的应用案例通过案例分析展示继承和多态如何在设计模式中发挥作用讨论设计模式如何提高程序设计的质量和可复用性第十章:课程回顾与拓展学习10.1 课程回顾总结本课程的重点内容和关键概念强调继承和多态在实际编程中的应用10.2 拓展学习资源提供一些拓展学习的资源和建议鼓励学生继续深入学习面向对象程序设计的其他方面第十一章:继承和多态的实际应用案例11.1 案例分析:图形库的设计通过分析图形库的设计,展示继承和多态如何用于实现复杂的图形操作。
Java程序设计教程第7章7.2 多 态
master.feed(xxx); ……
public void feed( XXX xxx ) { xxx.eat();
可否使用一个feed(Pet pet) 实现对所有宠物的喂食?
}
… … 频繁修改代码,代码可扩展性、可维护性差,
}
如何优化?
课堂操作——购置新车2-2
提前做完的同学可以尝试改进系统:
1. 循环从控制台选择汽车种类 2. 从控制台输入天数 3. 累加计算总租金
20/30
多态
总结
使用多态的好处
减少类中代码量 提高代码的可扩展性和可维护性
向上转型——子类转换为父类,自动进行类型转换
向下转型——父类转换为子类,结合instanceof运算符进行强 制类型转换
编写测试方法
调用主人类给狗狗喂的方法 调用主人类给企鹅喂的方法
为什么使用多态5-2
3/30
为什么使用多态5-3
问题
如果再领养XXX宠物,并需要给XXX喂食,怎么办?
添加XXX类,继承Pet类,实现吃食方法 修改Master类,添加给XXX喂食的方法
4/30
为什么使用多态5-4
主人类
练习
需求说明
使用多态实现喂养宠物功能 增加宠物猫并喂食,其健康值增加4
9/30
使用父类作为方法返回值实现多态
使用多态实现领养宠物
使用父类作为方法返回值 实现思路
在Master类添加领养方法getPet(String typeId ) 创建测试类,根据主人选择宠物类型编号来领养宠物
public class Master { public void feed( Dog dog ) { dog.eat(); } public void feed( Penguin pgn ) { pgn.eat(); }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java多态1. Java中除了static和final方法外,其他所有的方法都是运行时绑定的。
private 方法都被隐式指定为final的,因此final的方法不会在运行时绑定。
当在派生类中重写基类中static、final、或private方法时,实质上是创建了一个新的方法。
2.在派生类中,对于基类中的private方法,最好采用不同的名字。
3.包含抽象方法的类叫做抽象类。
注意定义里面包含这样的意思,只要类中包含一个抽象方法,该类就是抽象类。
抽象类在派生中就是作为基类的角色,为不同的子类提供通用的接口。
4.对象清理的顺序和创建的顺序相反,当然前提是自己想手动清理对象,因为大家都知道Java垃圾回收器。
5.在基类的构造方法中小心调用基类中被重写的方法,这里涉及到对象初始化顺序。
6.构造方法是被隐式声明为static方法。
7.用继承表达行为间的差异,用字段表达状态上的变化。
在JAVA中有两种多态是指:运行时多态和编译时多态。
关于类的多态性简介如下:多态(polymorphism)意为一个名字可具有多种语义.在程序设计语言中,多态性是指”一种定义,多种实现”.例如,运算符+有多种含义,究竟执行哪种运算取决于参加运算的操作数类型:1+2 //加法运算符“1” + “2” //字符串连接运算,操作数是字符串多态性是面向对象的核心特征之一,类的多态性提供类中成员设计的灵活性和方法执行的多样性.1、类多态性表现(1)方法重载重载表现为同一个类中方法的多态性.一个类生命多个重载方法就是为一种功能提供多种实现.编译时,根据方法实际参数的数据类型\个数和次序,决定究竟应该执行重载方法中的哪一个.(2)子类重定义从父类继承来的成员当子类从父类继承来的成员不适合子类时,子类不能删除它们,但可以重定义它们,使弗雷成员适应子类的新需求.子类重定义父类成员,同名成员在父类与子类之间表现出多态性,父类对象引用父类成员,子类对象引用子类成员,不会产生冲突和混乱.子类可重定义父类的同名成员变量,称子类隐藏父类成员变量.子类也可以重定义父类的同名成员方法,当子类方法的参数列表与父类方法参数列表完全相同时,称为子类方法覆盖(override)父类方法。
覆盖父类方法时,子类方法的访问权限不能小于父类方法的权限。
由于Object类的equals()方法比较两个对象的引用是否相等而不是值是否相等,因此一个类要覆盖Object类的equals()方法,提供本类两个对象比较相等方法.覆盖表现为父类与子类之间方法的多态性.java 寻找执行方法的原则是:从对象所属的类开始,寻找匹配的方法执行,如果当前类中没有匹配的方法,则逐层向上依次在父类或祖先类中寻找匹配方法,直到Object类.2、super 引用在子类的成员方法中,可以使用代词super引用父类成员.super引用的语法如下:super([参数列表]) //在子类的构造方法体中,调用父类的构造方法super.成员变量//当子类隐藏父类成员变量时,引用父类同名成员变量super.成员方法([参数列表]) //当子类覆盖父类成员方法时,调用父类同名成员方法*注意:super引用没有单独使用的语法3、多态性有两种:1)编译时多态性对于多个同名方法,如果在编译时能够确定执行同名方法中的哪一个,则称为编译时多态性. 2)运行时多态性如果在编译时不能确定,只能在运行时才能确定执行多个同名方法中的哪一个,则称为运行时多态性.方法覆盖表现出两种多态性,当对象获得本类实例时,为编译时多态性,否则为运行时多态性,例如:XXXX x1 = new XXXX(参数列表); //对象获得本类实例,对象与其引用的实例类型一致XXX xx1 = new XXX(参数列表);x1.toString(); //编译时多态性,执行XXX类的方法.xx1.toString(); //编译时多态性,执行XXXX类覆盖的方法.XXXX为XXX的父类.由于子类对象既是父类对象,父类对象与子类对象之间具有赋值相容性,父类对象能够被赋值为子类对象.例如,XXXX x2 = new XXX(参数列表); //父类对象获得子类实例,子类对象即是父类对象x2.toString(); //运行时多态x2声明为父类对象却获得子类XXX的实例,那么x2.toString()究竟执行父类方法还是执行子类覆盖的方法呢?这分为两种情况:取决于子类是否覆盖父类方法.如果子类覆盖父类方法,则执行子类方法;如果没有覆盖,则执行父类方法.在编译时,仅仅依据对象所属的类,系统无法确定到底应该执行那个类的方法,只有运行时才能确定,因此这是运行时多态.父类对象并不能执行所有的子类方法,只能执行那些父类中声明\子类覆盖的子类方法.在这样一个体系中,多态表现出多种形式的能力。
通用多态引用有相同结构类型的大量对象,他们有着共同的特征。
特定的多态涉及的是小部分没有相同特征的对象。
四种多态可做以下描述:强制的:一种隐式做类型转换的方法。
重载的:将一个标志符用作多个意义。
参数的:为不同类型的参数提供相同的操作。
包含的:类包含关系的抽象操作。
我将在讲述子类型多态前简单介绍一下这几种多态。
强制的多态强制多态隐式的将参数按某种方法,转换成编译器认为正确的类型以避免错误。
在以下的表达式中,编译器必须决定二元运算符…+‟所应做的工作:2.0 + 2.02.0 + 22.0 + "2"第一个表达式将两个double的操作数相加;Java中特别声明了这种用法。
第二个表达式将double型和int相加。
Java中没有明确定义这种运算。
不过,编译器隐式的将第二个操作数转换为double型,并作double型的加法。
做对程序员来说十分方便,否则将会抛出一个编译错误,或者强制程序员显式的将int转换为double。
第三个表达式将double与一个String相加。
Java中同样没有定义这样的操作。
所以,编译器将double转换成String类型,并将他们做串联。
强制多态也会发生在方法调用中。
假设类Derived继承了类Base,类C有一个方法,原型为m(Base),在下面的代码中,编译器隐式的将Derived类的对象derived转化为Base 类的对象。
这种隐式的转换使m(Base)方法使用所有能转换成Base类的所有参数。
C c = new C();Derived derived = new Derived();c.m( derived );并且,隐式的强制转换,可以避免类型转换的麻烦,减少编译错误。
当然,编译器仍然会优先验证符合定义的对象类型。
重载的多态重载允许用相同的运算符或方法,去表示截然不同的意义。
…+‟在上面的程序中有两个意思:两个double型的数相加;两个串相连。
另外还有整型相加,长整型,等等。
这些运算符的重载,依赖于编译器根据上下文做出的选择。
以往的编译器会把操作数隐式转换为完全符合操作符的类型。
虽然Java明确支持重载,但不支持用户定义的操作符重载。
Java支持用户定义的函数重载。
一个类中可以有相同名字的方法,这些方法可以有不同的意义。
这些重载的方法中,必须满足参数数目不同,相同位置上的参数类型不同。
这些不同可以帮助编译器区分不同版本的方法。
编译器以这种唯一表示的特征来表示不同的方法,比用名字表示更为有效。
据此,所有的多态行为都能编译通过。
强制和重载的多态都被分类为特定的多态,因为这些多态都是在特定的意义上的。
这些被划入多态的特性给程序员带来了很大的方便。
强制多态排除了麻烦的类型和编译错误。
重载多态像一块糖,允许程序员用相同的名字表示不同的方法,很方便。
参数的多态参数多态允许把许多类型抽象成单一的表示。
例如,List抽象类中,描述了一组具有同样特征的对象,提供了一个通用的模板。
你可以通过指定一种类型以重用这个抽象类。
这些参数可以是任何用户定义的类型,大量的用户可以使用这个抽象类,因此参数多态毫无疑问的成为最强大的多态。
乍一看,上面抽象类好像是java.util.List的功能。
然而,Java实际上并不支持真正的安全类型风格的参数多态,这也是java.util.List和java.util的其他集合类是用原始的ng.Object写的原因(参考我的文章"A Primordial Interface?" 以获得更多细节)。
Java 的单根继承方式解决了部分问题,但没有发挥出参数多态的全部功能。
Eric Allen有一篇精彩的文章“Behold the Power of Parametric Polymorphism”,描述了Java通用类型的需求,并建议给Sun的Java规格需求#000014号文档"Add Generic Types to the Java Programming Language."(参考资源链接)包含的多态包含多态通过值的类型和集合的包含关系实现了多态的行为.在包括Java在内的众多面向对象语言中,包含关系是子类型的。
所以,Java的包含多态是子类型的多态。
在早期,Java开发者们所提及的多态就特指子类型的多态。
通过一种面向类型的观点,我们可以看到子类型多态的强大功能。
以下的文章中我们将仔细探讨这个问题。
为简明起见,下文中的多态均指包含多态。