Java中的多态性
1:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
2:指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)下面会有代码详细解释。
3:在继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。即先查this对象的父类,没有就重头再查参数的父类
1:面向对象的三大特性:封装、继承、多态。
2:多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
3:实现多态的技术称为:动态绑定(dynamicbinding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
4:多态的作用:消除类型之间的耦合关系。
5:现实中,关于多态的例子不胜枚举。比方说按下 F1键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。
多态存在的三个必要条件
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。
1:父类中存在方法而子类中不存在
代码:
publicclass Animal {
//父类
publicvoid DoWork() {
System.out.println("———————————————————————");
System.out.println("******我存在与父类*******");
System.out.println("———————————————————————");
}
}
publicclass Dog extends Animal {//子类}
publicclass Test {
publicstaticvoid main(String[] args) {
Animal d = new Dog();
d.DoWork();
}
}
2:父类中不存在子类中存在
代码:
publicclass Animal {//父类}
publicclass Dog extends Animal {//子类
publicvoid DoWork() {
System.out.println("———————————————————————");
System.out.println("******我存在与子类*******");
System.out.println("———————————————————————");
}
}
publicclass Test {
publicstaticvoid main(String[] args) {
Animal d = new Dog();
d.DoWork();
}
}
这时就会提示报错因为在多态中创建了的对象用父类,则先要在父类中的类中检索若父类中没有,则会报错,在创建对象时先进行编译在运行。
3:子类父类都存在
publicclass Animal {//父类
publicvoid DoWork() {
System.out.println("———————————————————————");
System.out.println("******我存在与父类*******");
System.out.println("———————————————————————");
}
}
publicclass Dog extends Animal {//子类
publicvoid DoWork() {
System.out.println("———————————————————————");
System.out.println("******我存在与子类*******");
System.out.println("———————————————————————");
}
}
publicclass Test {
publicstaticvoid main(String[] args) {
Animal d = new Dog();
d.DoWork();
}
}
4:父类中含有静态变量(static)
publicclass Animal {//父类
publicstaticvoid DoWork() {
System.out.println("———————————————————————");
System.out.println("******我存在与父类*******");
System.out.println("———————————————————————");
}
}
publicclass Dog extends Animal {//子类
publicvoid DoWork() {
System.out.println("———————————————————————");
System.out.println("******我存在与子类*******");
System.out.println("———————————————————————");
}
}
publicclass Test {
publicstaticvoid main(String[] args) {
Animal d = new Dog();
d.DoWork();
}
}
为什么会出现这样的情况?
因为static是静态变量,他属于类属性,不是对象属性,调用时就等同于
Animal.DoWork();
1:继承类型的
问题:饲养员给动物喂食?
传统代码:
publicclass Cat extends Animal{//子类
publicvoid eat() {
System.out.println("我要鱼!!");}
}
publicclass Dog extends Animal {//子类
publicvoid eat() {
System.out.println("我要吃骨头!!");
}
}
publicclass Animal {
//父类
publicvoid eat() {
System.out.println("我要吃东西!!");
}
}
publicclass Test {
publicstaticvoid main(String[] args) {
//定义人这个对象
Person p = new Person();
Dog d = new Dog();
p.doWork(d);
Cat c = new Cat();
p.doWork(c);
}
}
publicclass Person {
/*调用主函数中的Dog和Cat的对象
* 因为此时的问题是饲养员喂养的东西所以必须在主函数中
* 把Dog和Cat的对象引用过来
*在这里也有方法的重载
*/
publicvoid doWork(Dog a){
a.eat();
System.out.println("狗吃肉骨头!");
}
publicvoid doWork(Cat c) {
c.eat();
System.out.println("猫吃鱼");
}
}
输出结果:
多态方法:
Instanceof:是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。(先得了解这个)。
语法:
result = object instanceof class
参数:Result:布尔类型。
Object:必选项。任意对象表达式。
Class:必选项。任意已定义的对象类。
说明:如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
因为父类子类的代码都一样所以就不写啦
publicclass Person {
/*调用主函数中的Dog和Cat的对象
* 因为此时的问题是饲养员喂养的东西所以必须在主函数中
* 把Dog和Cat的对象引用过来
*/
publicvoid doWork(Animal a){
if(ainstanceof Dog) {//这里运用instanceof来判断a属于那种对象
a.eat();//这里用了方法重载
System.out.println("狗喜欢吃骨头");
}elseif(ainstanceof Cat) {
a.eat();
System.out.println("猫喜欢吃鱼");
}
}
}
publicclass Test {
publicstaticvoid main(String[] args) {
Person p = new Person();
/*
* 因为Dog与Cat都属于Animal的子类,所以能这样用父类;
* Animal N(这里编译型) = new Dog()/Cat()
* 是运行型;
*/
Animal D = new Dog();
p.doWork(D);
Animal C = new Cat();
p.doWork(C);
}
}
这就是多态的方法,
2:接口类型的