首先,我们来看这两个文件中的关键代码:
- 在 [AbstractApplicationExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/base/AbstractApplicationExecute.java#L15-L36) 抽象类中,定义了一个抽象方法 [type()](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L45-L47):
public abstract String type();- 在 [ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 类中,实现了这个抽象方法:
@Override
public String type() {
return APPLICATION_EVENT_LISTENER;
}下面我来逐一回答你的问题:
1. 为什么 public abstract String type(); 特意标明 abstract?
在抽象类中声明一个方法为 abstract 有几个重要原因:
- 强制子类实现:抽象方法要求所有非抽象子类必须提供具体实现。这样可以确保子类不会遗漏重要的方法实现。
- 定义契约:抽象方法定义了一个契约,规定了子类应该提供什么功能,但不规定如何实现。
- 模板方法模式:抽象类可以定义模板方法,其中调用抽象方法,而具体实现由子类提供。
如果去掉 abstract 关键字,这个方法就会变成普通方法,需要提供具体实现:
// 普通方法需要提供实现
public String type() {
// 默认实现
return "default";
}这种情况下,子类可以选择是否覆盖这个方法,而不是强制要求实现。
2. [ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 不仅继承了抽象类也实现了接口,这两者是什么关系?
在 [ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 类中:
public class ApplicationStartEventListenerExecute
extends AbstractApplicationExecute
implements ApplicationListener<ApplicationStartedEvent>这表示:
继承抽象类 (
extends AbstractApplicationExecute):- 继承了父类的成员变量和方法实现
- 必须实现父类的抽象方法 ([type()](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L45-L47))
- 可以覆盖父类的非final方法
实现接口 (
implements ApplicationListener<ApplicationStartedEvent>):- 必须实现接口中定义的所有方法 (如 [onApplicationEvent()](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L39-L41))
- 接口只是定义了契约,不提供任何实现
3. 对成员属性和成员函数的复用区别
继承抽象类的复用:
- 可以复用父类的成员变量
- 可以复用父类的具体方法实现
- 可以覆盖父类的方法
实现接口的复用:
- 接口不能包含实例变量(除了常量)
- 接口只能定义方法签名,不提供实现(Java 8之后可以有默认实现)
- 实现类必须提供接口方法的具体实现
总的来说,继承抽象类更多是为了代码复用和扩展,而实现接口更多是为了满足契约和获得多态能力。
在这个例子中,[ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 通过继承 [AbstractApplicationExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/base/AbstractApplicationExecute.java#L15-L36) 获得了执行初始化任务的核心逻辑,同时通过实现 [ApplicationListener](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-component/src/main/java/com/damai/event/BaseSpringEventPublisher.java#L13-L51) 接口来响应Spring的事件机制。这种设计既获得了代码复用的好处,又满足了框架集成的需求。