面向对象 --- 多态
概念:
多态: 一种事物以多种形态存在,同样的引用调用同样的方法却做了不同的事情。
概述:
在Java里,多态是同一个行为具有不同表现形式或形态的能力,即对象多种表现形式的体现,就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
生活中的多态:
不同类型的打印机打印效果不同
打印机类型 | 打印效果 |
---|---|
黑白打印机 | 黑白纸张 |
彩色打印机 | 彩色纸张 |
手机app扫码支付
程序中的多态 :
父类引用和子类对象。同一种事物,由于条件不同,产生的结果也不同。
多态:同一个引用类型,使用不同的实例而执行不同操作。
实现多态的三个必要条件
(1)继承(2)重写 (3)父类引用指向子类对象
子类多态性的使用,是使用父类的引用,指向子类的对象,然后虚拟方法调用子类重写父类的方法。
示例:
abstract class Animal {
public abstract void shout(); // 定义抽象shout()方法
}
//定义Cat类继承Animal
class Cat extends Animal {
// 实现shout()方法
public void shout() {
System.out.println("喵喵...");
}
}
//定义Dog类继承Animal
class Dog extends Animal {
// 实现shout()方法
public void shout() {
System.out.println("汪汪...");
}
}
public class Duotai {
// 定义一个静态的animalShout()方法,接收一个Animal类型的对象
public static void animalShout(Animal animal) {
animal.shout();// 调用实际参数的shout()方法
}
public static void main(String[] args) {
Animal cat = new Cat();
Animal dog = new Dog();
animalShout(dog);
animalShout(cat);
// 运行结果:
// 汪汪...
// 喵喵...
}
}
Animal cat = new Cat();和 Animal dog = new Dog(); 两行代码实现了父类类型变量引用不同的子类对象。
调用animalShout()方法时,将父类引用的两个不同子类对象分别传入,结果打印出了 “汪汪…” 和 “喵喵…” 。
由此可见,多态不仅解决了方法同名的问题,而且还使程序变得更加灵括,从而有效地提高程序的可扩展性和可维护性。
对象的类型转换
在多态的学习中,涉及到将子类对象当作父类类型使用的情况,例如下面两行代码:
Animal cat = new Cat(); //将Cat对象当作Animal类型来使用
Animal dog = new Dog(); //将Dog对象当作Animal类型来使用
- 将子类对象当作父类使用时不需要任何显式地声明,需要注意的是,此时不能通过父类变量去调用子类中的某些方法。
- 这种不需要显式声明的类型转换叫自动类型转换。
对于animalShout()方法来说,传入的对象可以是Animal类型,还可以是Animal的子类型,它要怎么知道传入的到到底是哪一个类型呢?Java提供了一个instanceof关键字来判断一个对象的类型,其使用格式如下:
对象(或对象的引用变量) instanceof 类(或接口)
利用instanceof进行类型判断的好处就是避免了强制类型转换过程中类型不匹配的错误。例如:
public static void animalShout(Animal animal) {
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.shout();
} else if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.shout();
} else {
animal.shout();
}
}
抽象类和接口
在上面,我们定义了一个抽象类,抽象类中有一个抽象方法shout(),然后其他具体的动物类继承这个抽象类重写它的shout()方法。但是,在实际开发中,我们很少去主动定义一个抽象类,我们每天写代码,更多的是创建一个接口,然后定义接口实现类,在实现类中做对应的业务逻辑处理。
首先,我们先来聊一下抽象类和接口的相同点和不同点吧。
- 在java中,抽象类和接口都不能直接进行实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
- 抽象类要被子类继承,接口要被类实现。
- 接口只能做方法申明,抽象类既可以做方法申明,还可以做方法实现。
- 接口中的变量只能是静态的公共变量,抽象类中的变量是普通的变量,即常量
- 抽象类中可以没有抽象方法。
- 如果一个类中有抽象方法,那么这个类是一个抽象类。
- 接口可以继承接口,并且可以多继承,但是类只能单继承。
上一篇: C++面向对象多态之虚析构函数和纯虚函数