接口 & 抽象类
一、接口和抽象类
接口:用来封装代码,告诉外界提供了哪些功能(方法抽象),对行为的抽象。
-
接口就是一种特殊的abstract class,但是比abstract class更加抽象
-
在接口中声明方法,实现类实现接口—— 接口中方法不能在接口中实现,它需要一个实现类来实现它(通过具体的实现类来实例化:实现类 a = new 实现类() )
抽象类:用来把同一类事物抽象为一个类(代码复用),对本质上相同的行为、属性的抽象。
-
抽象类实现接口时,可以完全覆盖/重写 接口中的方法,也可以只重写接口中的某几个方法。
|
接口 |
抽象类 | |
---|---|---|---|
定义 |
Interface |
abstract class |
|
设计理念 |
对行为的抽象 作用是降低耦合,对行为进行约束 |
对具体事物的抽象,包括属性、行为 作用是复用,即复用逻辑相同的代码 |
|
构成 |
方法:抽象方法(隐式默认 public abstract) 常量:默认 public static final |
方法:抽象方法、普通方法 变量:成员变量 常量:默认 public static final |
接口只包含抽象方法 抽象类可以包含抽象方法、非抽象方法 |
访问修饰符 |
接口方法默认都是public,不能有其他修饰符。 |
抽象方法可以有public、protected和default修饰符 |
|
继承/实现 |
接口extends多接口 抽象类implements多接口 子类implements多接口 |
抽象类extends单抽象类 子类extends单抽象类 |
接口:子类使用implements来实现接口。需要提供接口中所有方法的实现。 抽象类:子类使用extends来继承抽象类。如果子类不是抽象类,需要提供抽象类中所有抽象方法的实现。 |
接口的设计目的,是对类的行为进行约束(更准确的说是一种“有”约束,因为接口不能规定类不可以有什么行为),也就是提供一种机制,可以强制要求不同的类具有相同的行为。它只约束了行为的有无,但不对如何实现行为进行限制。对“接口为何是约束”的理解,我觉得配合泛型食用效果更佳。
而抽象类的设计目的,是代码复用。当不同的类具有某些相同的行为(记为行为集合A),且其中一部分行为的实现方式一致时(A的非真子集,记为B),可以让这些类都派生于一个抽象类。在这个抽象类中实现了B,避免让所有的子类来实现B,这就达到了代码复用的目的。而A减B的部分,留给各个子类自己实现。正是因为A-B在这里没有实现,所以抽象类不允许实例化出来(否则当调用到A-B时,无法执行)。
链接:https://www.zhihu.com/question/20149818/answer/150169365
资料:https://www.jianshu.com/p/c4f023d02f0c
二、使用
2.1 使用选择
首先看是对方法抽象,还是对方法+属性的抽象
其次看是否需要实现一些通用方法
综合以上来考虑使用接口还是抽象类
2.2 两者结合使用
接口 <--- 抽象类 <--- 实现类
-
接口:定义方法
-
抽象类:实现部分方法(确定且重复的);添加新的方法
-
实现类:实现剩余的方法
即,在业务比较复杂时,开始先抽象出未实现的接口,然后把确定且重复的接口实现在抽象类中,最后在一个或多个子类(一般有多个子类)中实现未实现的接口方法。这样做有两个好处:1,抽象分层,逻辑清晰;2,多人合作中分工明确,每个人负责的业务子类只需要实现自己的接口就好,重复的就直接调用抽象类已实现的。Java源码中最明显得例子就是HashMap先继承抽象类AbstractMap,AbstractMap是实现了Map接口的抽象类。
2.3 如何获取并使用某个实现类
1、直接使用(单实现类)
@Autowired private ResultRepositoryService resultRepository;
2、@Qualifier显示指定bean名称(多实现类)
@Autowired @Qualifier("paramVerifyServiceImpl") private IParamVerifyService paramVerifyService;
3、applicationContext.getBean(beanName)
@Component public class SpringBeanUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * 根据bean唯一标识获取实例 * * @param beanName bean的名称标识 * @param <T> 实例类型 * @return 实例 */ public static <T> T getBean(String beanName) { return (T) applicationContext.getBean(beanName); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话