活动地址:CSDN21天学习挑战赛
面向对象——多态详解
前面我们对面向对象的三大特征:封装、继承、多态进行了简单的梳理,今天我们对多态进行一个更深入的学习。
什么是多态?
多态(Polymorphism)属于面向对象的三大特征之一,它的前提是封装形成独立体,独立体之间存在继承关系,从而形成多态机制。多态是同一个行为具有多个不同表现形式的能力。多态就是“同一个行为”发生在“不同对象上”会产生不同的效果。
多种形态,多种状态,编译和运行有两个不同的状态
- 编译期叫做静态绑定
- 运行期叫做动态绑定
方法重载与方法覆盖(重写)的区别
方法重载发生在同一个一个类中
方法覆盖 是发生在具有继承关系的父子类之间
方法重载是在一个类中,方法名相同,参数列表不同
方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:方法名一致、参数列表一致、返回值类型一致。
多态的基础语法
向上转型和向下转型
在Java中允许两种这样的语法出现,一种是向上转型(Upcasting),一种是向下转型(Downcasting),向上转型是指子类型转换为父类型,可理解为自动类型转换,向下转型是指父类型转换为子类型,又可以理解为强制类型转换。调用子类特有方法时必须进行向下转型。
注意:无论是向上转型还是向下转型,两种类型之间必须是继承关系,没有继承关系编译器会报错!!!
示例程序:
package com.shouyerenst.OOP;
public class Animal {
public void move(){
System.out.println("动物在移动!!!");
}
}
class Cat extends Animal{
//对move方法重写
public void move(){
System.out.println("猫在走猫步!!!");
}
//Cat类特有的方法
public void catchMouse(){
System.out.println("猫正在抓老鼠!!!");
}
}
class Bird extends Animal{
//对move方法重写
public void move(){
System.out.println("鸟儿在飞翔!!!");
}
public void sing(){//Bird特有的方法
System.out.println("鸟儿在歌唱!!!");
}
}
测试程序:
package com.shouyerenst.OOP;
public class AnimalTest {
public static void main(String[] args) {
Animal a1 = new Animal();
a1.move();
Cat c1 = new Cat();
c1.move();
Bird b1 = new Bird();
b1.move();
System.out.println("--------------------------");
//父类型引用允许指向子类型引用
//向上转型
Animal a2 = new Cat();
a2.move();
Animal a3 = new Bird();
a3.move();
//向下类型转换
//这里编译器认为a4是一个Animal类型,如果要使用Cat(Animal的子类)中特有的方法,就必须向下转型了
Animal a4 = new Cat();
Cat x = (Cat) a4;
x.catchMouse();
/*
下面代码在编译的时候是没有任何问题的,但是运行时会出现java.lang.ClassCastException(类型转换异常)
Animal a5 = new Bird();
Cat y = (Cat) a5;
y.catchMouse();
*/
}
}
AnimalTest中注释代码错误分析:
编译阶段:(静态绑定)
编译器认为a5是一个Animal类型,而Animal和Cat具有继承关系,所以可以向下转型为Cat对象,调用Cat类独有方法,可以编译通过
运行阶段:(动态绑定)
在堆内存中创建对象的时候实际上创建的是Bird类型对象,而Bird类与Cat类并不具有继承关系,所以无法完成向下转型,也无法调用Cat类的独有方法。这里出现的异常叫做java.lang.ClassCastException(类型转换异常),这是一个同空指针异常同样重要的异常类型,我们需要注意。
如何避免ClassCastException
instanceof运算符
有时候需要在运行时判断一个对象是否属于某个引用类型,这时可以使用instanceof运算符,instanceof运算符语法格式如下:
obj instanceof type
其中obj是一个对象,type是引用类型,如果obj对象是type引用类型实例则返回true,否则false。
测试程序中的注释代码就可以改成如下格式:
Animal a5 = new Bird();
if(a5 instanceof Cat){
Cat y = (Cat) a5;
y.catchMouse();
} else if (a5 instanceof Bird) {
Bird y = (Bird) a5;
y.sing();
}
任何时间,任何地点,在进行向下转型(强制类型转换)的时候我们需要使用instanceof运算符进行判断,避免出现类型转换异常,这是Java中规范要求的。
多态在开发中的作用
多态在开发中的作用是降低程序的耦合度,提高程序的扩展力。
举个栗子!!!
public class Master{
public void feed(Dog d){}
public void feed(Cat c){}
}
//以上代码中表示:Master和Dog以及Cat的关系很紧密(耦合度搞),导致其扩展力很差。
public class Master{
public void feed(Pet pet){}
}
//以上代码表示:Master和Dog以及Cat的关系就脱离了,Master关注的是Pet类,降低了Master和Dog以及Cat类的耦合性,提高了软件的扩展性。
总结
现在我们再来回顾面向对象的三大特征:封装、基础、多态
他们之间的关系是一环扣一环
首先得封装成一个整体才有了继承的概念
有了继承关系才有了多态的实现 —>Animal a1 = new Cat();
感觉不错的话,动手点个赞吧!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/125491.html