多态
一、多态的概念
多态是面向对象编程中的一个重要特性,它允许不同类的对象对同一消息(也就是方法调用)做出不同的响应,简单来说就是"多种形态"。在 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
等符合接口的实例)下可以有不同的行为,使得代码能够根据实际赋值的对象来灵活地执行相应的操作。
- 当通过
评论区