多态
- 格式:pptx
- 大小:759.84 KB
- 文档页数:20
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. 重载是编译时多态调⽤重载的⽅法,在编译期间就要确定调⽤的⽅法是谁,如果不能确定则编译报错。
多态的概念和作⽤(深⼊理解)多态是⾯向对象的重要特性,简单点说:“⼀个接⼝,多种实现”,就是同⼀种事物表现出的多种形态。
编程其实就是⼀个将具体世界进⾏抽象化的过程,多态就是抽象化的⼀种体现,把⼀系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进⾏对话。
对不同类的对象发出相同的消息将会有不同的⾏为。
⽐如,你的⽼板让所有员⼯在九点钟开始⼯作, 他只要在九点钟的时候说:“开始⼯作”即可,⽽不需要对销售⼈员说:“开始销售⼯作”,对技术⼈员说:“开始技术⼯作”, 因为“员⼯”是⼀个抽象的事物, 只要是员⼯就可以开始⼯作,他知道这⼀点就⾏了。
⾄于每个员⼯,当然会各司其职,做各⾃的⼯作。
多态允许将⼦类的对象当作⽗类的对象使⽤,某⽗类型的引⽤指向其⼦类型的对象,调⽤的⽅法是该⼦类型的⽅法。
这⾥引⽤和调⽤⽅法的代码编译前就已经决定了,⽽引⽤所指向的对象可以在运⾏期间动态绑定。
再举个⽐较形象的例⼦:⽐如有⼀个函数是叫某个⼈来吃饭,函数要求传递的参数是⼈的对象,可是来了⼀个美国⼈,你看到的可能是⽤⼑和叉⼦在吃饭,⽽来了⼀个中国⼈你看到的可能是⽤筷⼦在吃饭,这就体现出了同样是⼀个⽅法,可以却产⽣了不同的形态,这就是多态!多态的作⽤:1. 应⽤程序不必为每⼀个派⽣类编写功能调⽤,只需要对抽象基类进⾏处理即可。
⼤⼤提⾼程序的可复⽤性。
//继承2. 派⽣类的功能可以被基类的⽅法或引⽤变量所调⽤,这叫向后兼容,可以提⾼可扩充性和可维护性。
//多态的真正作⽤,以前需要⽤switch实现----------------------------------------------------多态是⾯向对象程序设计和⾯向过程程序设计的主要区别之⼀,何谓多态?记得在CSDN⾥⼀篇论C++多态的⽂章⾥有⼀名话:“龙⽣九⼦,⼦⼦不同”多态就是同⼀个处理⼿段可以⽤来处理多种不同的情况,在钱能⽼师的《C++程序设计教程》书中有这样⼀个例⼦:定义了⼀个⼩学⽣类[本⽂全部代码均⽤伪码]class Student{public:Student(){}~Student(){}void 交学费(){}//......};⾥⾯有⼀个 “交学费”的处理函数,因为⼤学⽣和⼩学⽣⼀些情况类似,我们从⼩学⽣类中派⽣出⼤学⽣类:class AcadStudent:public Student{public:AcadStudent(){}~ AcadStudent(){}void 交学费(){}//.......};我们知道,中学⽣交费和⼤学⽣交费情况是不同的,所以虽然我们在⼤学⽣中继承了中学⽣的"交学费"操作,但我们不⽤,把它重载,定义⼤学⽣⾃⼰的交学费操作,这样当我们定义了⼀个⼩学⽣,⼀个⼤学⽣后:Student A;AcadStudent B;A.交学费(); 即调⽤⼩学⽣的,B.交学费();是调⽤⼤学⽣的,功能是实现了,但是你要意识到,可能情况不仅这两种,可能N种如:⼩学⽣、初中⽣、⾼中⽣、研究⽣.....它们都可以以Student[⼩学⽣类]为基类。
简述虚函数实现多态的原理
虚函数是C++中支持多态的一种机制,多态是指同一函数在不同对象上产生不同的行为。
虚函数实现多态的原理是通过使用虚表(Vtable)和虚指针(Vptr)实现。
虚表是一个指针数组,它保存了类中所有虚函数的地址。
当一个对象被创建时,会在其内存布局中添加一个指向该类虚表的虚指针。
当调用一个虚函数时,编译器会通过该对象的虚指针查找对应虚表,进而找到虚函数的地址,然后执行该函数。
使用虚函数实现多态的过程如下:
1. 定义一个基类,并将其中需要实现多态的成员函数声明为虚函数。
2. 派生出子类,并根据需要重写基类的虚函数。
3. 通过基类指针或引用调用虚函数时,编译器会根据实际对象类型确定调用哪个版本的虚函数。
由于虚函数是在运行时才确定的,所以可以实现动态绑定,使程序具有更高的灵活性和可扩展性。
遗传多态现象遗传多态现象(genetic polymorphism)是指在一个群体中,同时和经常存在的两种或两种以上的变异型或基因型,每种类型的频率比较高,一般认为每种变异型超过1%即可定为多态现象,不足1%的称为罕见变异型。
人类存在多种遗传多态现象(多态性),主要有染色体多态性、酶和蛋白质多态性、抗原多态性的DNA多态性五类。
1.染色体多态性染色体的多态性又称异态性(heteromorphism)是指正常人群中经常可见到各种染色体形态的微小变异。
这种变异主要表现为同源染色体大小形态或着色等方面的变异。
多态性是可遗传的,并且通常仅涉及一对同源染色体中的一个。
例如表现的D和G组的随体增大、重复(双随体)或缺如,短臂的长短,1、9、16号染色体的次缢痕区加长或缩短,染色体着线粒区的荧光强度变异等。
Y染色体长臂的长度变异,可大于F组,也可小于G组,这种变异可能有民族差异。
染色体多态性的临床意义尚不清楚,在产前诊断中,染色体多态性可分胎儿细胞和母体细胞;可探讨异常染色体不分离的来源,有利于对患者家庭进行婚育的指导。
此外,可用于鉴定不同个体,对法医学中的亲权鉴定有一定的意义。
2.蛋白质多态性现在认为,人类结构蛋白质的多态性是一种普遍现象。
例如结合珠蛋白(haptoglobin,Hp)是一种糖蛋白,其生理功能在于Hp和血红蛋白结合后不能透过肾小球膜,因而红细胞破坏后释出的血红蛋白不能被肾清除,既避免铁的大量丢失,也可保护肾免受损害。
构成Hp分子的肽链有α和β链二种。
Hp多态性主要是α链的遗传变异。
α链有α1和α2二种。
α1中又有αIs和αIF二种亚型,各由84个氨基酸组成,两者区别在于第54位氨基酸(αIF为赖氨酸,αIs为谷氨酸),因此可以推断这一区别是通过一次点突变形成。
α2则由143个氨基酸组成。
从α链一级结构分析,Hpα2是HpαIF的N端71个氨基酸和HpISC端的72个氨基酸连接而成,即发生了错误配对和不等交换,形成了与HbLepore相似的融合基因。
重载和多态的区别多态性也是面向对象方法的一个重要特性.多态性是指在在程序中出现的"重名"现象,即在一个程序中相同的名字可以表示不同的实现.在JAVA中,多态性主要表现在如下两个方面:1方法重载.通常指在同一个类中,相同的方法名对应着不同的方法实现,但是方法的参数不同.2成员覆盖.通常指在不同类父类和子类中,允许有相同的变量名,但是数据类型不同;也允许有相同的方法名,但是对应的方法实现不同.在重载的情况下,同一类中具有相同的名字的方法.如何选择它的方法体呢?不能使用类名来区分,通常采用不同的方法形参表,区分重载要求形参在类型,个数和顺序的不同,在定义重载方法时,应在方法的形参的类型,个数和顺序有所不同,以便在选择时能够区别开来.在覆盖的情况下,同名的方法存在于不同的类中,在调用方法只要指明其方法所归属的类名就可以了.例如class Shape {void draw {}void erase {}}class Circle extends Shape {void draw {System.out.println"Circle.draw";}void erase {System.out.println"Circle.erase"; }}class Square extends Shape {void draw {System.out.println"Square.draw";}void erase {System.out.println"Square.erase";}}class Triangle extends Shape {void draw {System.out.println"Triangle.draw";}void erase {System.out.println"Triangle.erase";}}public class Test {public static Shape randShape {switchintMath.random * 3 {default:case 0: return new Circle;case 1: return new Square;case 2: return new Triangle;} }public static void mainString[] args {Shape[] s = new Shape[9];forint i = 0; i < s.length; i++ s[i] = randShape;forint i = 0; i < s.length; i++ s[i].draw;}}输出结果Triangle.drawCircle.drawTriangle.drawTriangle.drawTriangle.drawSquare.drawSquare.drawTriangle.drawCircle.drawTriangle.eraseCircle.eraseTriangle.eraseTriangle.eraseTriangle.eraseSquare.eraseSquare.eraseTriangle.eraseCircle.erasePress any key to continue...又一次执行Triangle.drawTriangle.drawCircle.drawCircle.drawCircle.drawTriangle.drawTriangle.drawSquare.drawCircle.drawTriangle.eraseTriangle.eraseCircle.eraseCircle.eraseCircle.eraseTriangle.eraseTriangle.eraseSquare.eraseCircle.erasePress any key to continue...两次执行结果不同的原因是其中的Math.random这个类导致的,math.random得到的数是0-1之间的随机数.写到这里,我突然想到了方法重载,那么它和多态,覆盖有什么区别呢?到GOOGLE是搜素了一下,不少.不过,最重要的一点区别是:通过方法重载进而实现对象的多态性.方法重载是指功能相同的多个方法使用同一个方法名.同名的多个方法的参数要有所不同,即在参数类型,参数个数和参数顺序上要有所区别,以便作为选择某个方法的根据.通常只有功能相同的方法进行重载才有意义.例如:计算两个数之和的重载方法定义如下:int addint i,int j{retrun i+j;}float addfloat i,float j{retrun i+j;}double adddouble i,double j{retrun i+j;}重载方法的选择通常是在编译时进行.系统根据不同的参数类型,个数或顺序,寻找最佳匹配方法.方法类型不参与匹配.下面是搜到的一些例子.public class Base{int a,b;public Baseint x,int y{a = x;b = y;}public int add{return a + b;}public void addint x,int y{int z;z = x + y;}}上面这段代码就是重载~~~他有三个特征1:方法名必须一样“add“。
面向对象的三种方法
面向对象编程是一种常见的编程范式,主要思想是将问题分解成一系列对象,通过对象之间的交互来解决问题。
在面向对象编程中,有三种主要的方法,分别是继承、封装和多态。
1. 继承
继承是一种将已有类的属性和方法传递给新类的方式。
在继承中,我们可以定义一个基类(也称为父类或超类),然后创建一个或多个派生类(也称为子类)。
子类可以继承父类的属性和方法,也可以添加自己的属性和方法。
继承可以减少代码的重复,提高代码的复用性,并且可以简化类的层次结构。
2. 封装
封装是指将类的内部数据和方法隐藏在类的外部,只暴露一些公共接口给外部使用。
通过封装,我们可以隐藏一些细节,使得代码更加安全和易于维护。
封装还可以提高代码的可复用性,因为我们可以将类的实现细节隐藏并重新使用。
3. 多态
多态是指在不同的情况下,同一种对象可以表现出不同的形态。
多态可以通过继承和接口的方式实现。
在继承中,一个子类可以重写父类的方法,从而改变其行为。
在接口中,多个类可以实现同一个接口,但是具体实现方式可以不同。
多态可以提高代码的灵活性和可扩展性。
总之,继承、封装和多态是面向对象编程中的三种重要方法。
通过使用它们,我们可以提高代码的复用性、可维护性和可扩展性,从而更好地解决编程中的问题。
java多态实验报告Java多态实验报告引言:Java是一种面向对象的编程语言,多态是其核心特性之一。
本实验旨在通过编写代码并运行实验,深入理解Java中的多态概念和使用方法。
实验目的:1. 理解多态的概念和原理;2. 掌握多态的使用方法和技巧;3. 通过实验加深对多态的理解和应用。
实验步骤:1. 创建一个抽象类Animal,并定义一个抽象方法makeSound();2. 创建两个继承自Animal的子类:Dog和Cat,并分别实现makeSound()方法;3. 在主函数中创建一个Animal类型的数组,包含两个元素,分别为Dog和Cat 的实例;4. 遍历数组,调用每个元素的makeSound()方法;5. 运行程序,观察输出结果。
实验结果:通过运行实验代码,我们可以看到Dog和Cat的实例都调用了makeSound()方法,但输出的结果却不同。
这就是多态的体现。
多态性允许我们在父类Animal的引用下,调用子类Dog和Cat的方法,实现了代码的灵活性和扩展性。
实验分析:1. 多态的概念:多态是指同一种类型的对象,在不同的情况下表现出不同的行为。
在本实验中,Dog和Cat都是Animal的子类,它们都继承了makeSound()方法,但实现方式不同,因此在调用时会表现出不同的行为。
2. 多态的原理:多态的实现依赖于继承和方法重写。
通过将子类对象赋值给父类引用,实现了对子类对象的调用。
在运行时,会根据实际对象的类型来确定调用哪个方法。
3. 多态的优势:多态使代码更加灵活和可扩展。
当需要新增一种动物时,只需创建一个新的子类并实现makeSound()方法,不需要修改原有的代码,即可实现新增功能。
4. 多态的应用场景:多态常用于面向对象的设计和开发中,尤其是在需要处理多种类型对象的情况下。
通过使用多态,可以简化代码结构,提高代码的可读性和可维护性。
实验总结:通过本次实验,我深入理解了Java中的多态概念和使用方法。