多态
一、多态的概念
多态是面向对象编程中的一个重要特性,它允许不同类的对象对同一消息(也就是方法调用)做出不同的响应,简单来说就是"多种形态"。在 Java 等面向对象语言中,多态主要通过继承、接口实现以及方法重写(覆盖)来体现。
多态是指同一行为作用于不同对象时,可以表现出多种不同的形式和结果来。例如,子类继承父类子类继承父类并覆盖其方法后,用父类引用指向子类对象并调用该方法时,实际执行的是子类的方法。
这种根据对象实际类型而非声明类型来确定执行方法的行为,就是多态性的体现。多态主要通过继承和接口实现,允许同一接口有多种不同的实现方式。
二、多态的分类
- 编译时多态,又称静态绑定,是指编译器在编译时通过检查引用类型的方法是否存在,来定位到相应的类及其方法,而不检查实际对象是否支持该方法。编译时多态主要体现在方法重载上,即根据参数类型、数量和顺序,在编译时确定要执行的方法。
- 运行时多态,又称动态绑定,是指程序在运行时根据对象的实际类型来确定调用哪个方法,而不是在编译时确定。这意味着方法的具体实现取决于对象的实际类型,而非其声明类型。父类引用可以指向不同的子类对象,使得相同方法调用产生不同的行为结果。通过运行时确定具体执行的方法,代码具有更好的扩展性和可维护性。
三、多态三个必要条件:
严格来说,多态需要具备以下三个条件。
- 继承:子类继承父类或实现接口。
- 重写:子类覆盖父类的方法。
- 父类声明子类:使用父类引用来声明子类对象。
四、多态的好处,为什么要用多态?
在面向对象设计中,"开闭原则"是非常重要的一条。即系统中的类应该对扩展开放,而对修改关闭。这样的代码更可维护和可扩展,同时更加简洁与清晰。
五、案例
使用工厂方法模式设计一个程序用来读取各种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReader),例如GIF图片读取器(GifReader)用于读取GIF格式的图片、JPG图片读取器(JpgReader)用于读取JPG格式的图片,在设计时,要充分考虑系统的灵活性和可扩展性。

代码如下
ImageReaderFactory接口
public interface ImageReaderFactory {
public ImageReader createImage();
}
ImageReader接口
public interface ImageReader {
public void readImage();
}
JpgReaderFactory类
public class JpgReaderFactory implements ImageReaderFactory {
public JpgReaderFactory(){
}
public ImageReader createImage(){
return new JpgReader();
}
}
JpgReader类
public class JpgReader implements ImageReader {
public JpgReader(){
}
public void readImage(){
System.out.println("读取Jpg图片");
}
}
GifReaderFactory类
public class GifReaderFactory implements ImageReaderFactory {
public GifReaderFactory(){
}
public ImageReader createImage(){
return new GifReader();
}
}
GifReader类
public class GifReader implements ImageReader {
public GifReader(){
}
public void readImage(){
System.out.println("读取Gif图片");
}
}
测试类Client
public class Client {
public static void main(String[] args) {
ImageReaderFactory imageReaderFactory = new GifReaderFactory();
ImageReader imageReader = imageReaderFactory.createImage();
imageReader.readImage();
jpgMethod();
}
public static void jpgMethod() {
ImageReaderFactory imageReaderFactory = new JpgReaderFactory();
ImageReader imageReader = imageReaderFactory.createImage();
imageReader.readImage();
}
}
六、多态在案例中的体现
- 基于接口实现的多态:
- 在提供的代码里,有
ImageReaderFactory接口和ImageReader接口。JpgReaderFactory类实现了ImageReaderFactory接口,JpgReader类实现了ImageReader接口。 - 对于
ImageReaderFactory接口,当执行ImageReaderFactory imageReaderFactory = new JpgReaderFactory();这行代码时,就体现了多态性。这里定义了一个ImageReaderFactory接口类型的变量imageReaderFactory,但实际将JpgReaderFactory(一个具体实现了该接口的类)的实例赋值给了它。这意味着,从代码层面看,imageReaderFactory变量可以代表任何实现了ImageReaderFactory接口的类的实例,后续代码只通过这个接口类型的变量来操作,而不用关心具体是哪个实现类的对象,只要符合接口规范就行。 - 同理,对于
ImageReader接口,ImageReader imageReader = imageReaderFactory.createImage();这行代码中,imageReader变量是ImageReader接口类型,它接收了JpgReader(实现该接口的具体类)的实例,同样展示了多态,即不管是哪种实现ImageReader接口的类的对象,都可以通过这个接口类型变量统一调用readImage方法。
- 在提供的代码里,有
-
方法重写(覆盖)与多态的关联:
- 在
JpgReader类中重写了ImageReader接口里定义的readImage方法,重写时遵循了方法签名(方法名、参数列表、返回类型等要和接口中定义的一致,对于接口中定义返回类型为接口类型的情况,实现类重写方法返回的具体实现类要满足接口类型要求,比如这里ImageReader接口要求返回类型为ImageReader,JpgReader返回自身实例满足要求)相同的规则。 - 当通过
imageReader.readImage();调用这个方法时(此时imageReader实际指向的是JpgReader的实例),会执行JpgReader类里重写后的readImage方法逻辑(也就是输出"读取Jpg图片"),而不是ImageReader接口中抽象定义的那个未具体实现的方法逻辑。如果后续有其他类(比如PngReader类假设实现了ImageReader接口并也重写了readImage方法),同样通过ImageReader接口类型变量调用readImage方法时,就会执行对应类里重写后的逻辑,这就是不同对象(不同实现类的实例)对同一方法调用(readImage方法调用)做出不同响应,充分体现了多态性。
- 在
- 类型声明与实际对象类型差异
- 在
ImageReaderFactory imageReaderFactory = new JpgReaderFactory();这行代码中,变量imageReaderFactory的类型被声明为ImageReaderFactory接口类型。这是一种抽象的类型定义,表示这个变量应该遵循ImageReaderFactory接口所规定的行为规范。 - 然而,实际赋值给这个变量的是
JpgReaderFactory类的实例。JpgReaderFactory是一个具体的类,它实现了ImageReaderFactory接口,这就产生了类型上的差异。这种差异是多态的一个重要体现,因为代码是基于接口(抽象类型)来操作的,但可以使用不同的具体实现类的对象来满足这个接口的要求。
- 在
- 方法调用的灵活性和多样性
- 当通过
imageReaderFactory变量调用方法时,例如imageReaderFactory.createImage();,由于imageReaderFactory的类型是ImageReaderFactory接口,编译器只知道它可以调用ImageReaderFactory接口中定义的方法(在这里是createImage方法)。 - 但是,实际执行的方法是由赋值给
imageReaderFactory的具体对象(也就是JpgReaderFactory的实例)来决定的。如果将来有另一个类(比如PngReaderFactory)也实现了ImageReaderFactory接口,并且在jpgMethod函数中,imageReaderFactory被赋值为PngReaderFactory的实例,那么同样的createImage方法调用会执行PngReaderFactory类中实现的createImage方法,产生不同的结果。 - 这就体现了多态性,即相同的方法调用(
createImage)在不同的具体对象(JpgReaderFactory或PngReaderFactory等符合接口的实例)下可以有不同的行为,使得代码能够根据实际赋值的对象来灵活地执行相应的操作。
- 当通过
评论区