接口和抽象有什么区别?
接口和抽象是 Java 面向对象设计的两个基础机制。
接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到API 定义和实现分离的目的。
- 接口不能实例化,
- 接口不能包含任何非常量成员,任何 field 隐含 public field final的意义
- 非静态方式实现,要么是抽象方法,要么是静态方法。
抽象类不能实例化,用 abstract 关键字修饰 class, 其主要目的是代码重用。
- 抽象类和普通 Java 类在形式上没有太大区别。可以有一个或者多个抽象方法,- 抽象类大多用于抽取 Java 类共用方法实现或者共同成员变量。然后通过继承的方式到达代码复用的目的。
接口和抽象区别
- 接口 Java 类实现 interface 使用 implements 关键词
- 继承 抽象类是使用 extends 关键词
- 支持多重继承:接口支持;抽象类不支持;类不支持;
- 支持抽象函数:接口语义上支持;抽象类支持;类不支持;
- 允许函数实现:接口不允许;抽象类支持;类允许;
- 允许实例化:接口不允许;抽象类不允许;类允许;
- 允许部分函数实现:接口不允许;抽象类允许;类不允许。
- 定义的内容:接口中只能包括public函数以及public static final常量;抽象类与类均无任何限制。
- 使用时机:当想要支持多重继承,或是为了定义一种类型请使用接口;
当打算提供带有部分实现的“模板”类,而将一些功能需要延迟实现请使用抽象类;当你打算提供完整的具体实现请使用类。
public class ArrayLis<E> extends AbsractLis<E> implements Lis<E>, RandomAccess, Cloneable, java.io.Serializable { //... }
抽象的极限性
Java 不支持多继承。Java 类可以实现多个接口,因为接口是抽象方法的集合,采用声明抽象方法的方式,但是并不能通过扩展多个抽象类来重用逻辑。
还有一些场景,需要抽象与具体实例化无关的通用逻辑,比如 Utils 类,但是如果采用抽象类,这样就存在单继承的问题。
面向对象设计
面向对象的基本要素:封装,继承,多态。
- 封装的目的是隐藏事务内部的实现细节,以便提高安全性和简化编程。封装提供了合理边界,避免外部调用者接触内部细节。比如,多线程编程是,暴露内部状态,冗余导致并发修改的问题。
- 继承是代码复用的基础机制,继承是一种紧耦合的关系,父类代码修改,子类行为会跟着变动。如果过度滥用,会起到不好的效果。
- 多态,说到多态,会立即想到重写(override) 和重载 (overload),向上转型。
- 重写是父子类中相同名字和参数的方法,不同的实现。
- 重载是相同名字方法,但是不同的参数。
要注意的是 方法名称和参数一致,但是返回值不同,这样不是重载,编译会报错!!
public int doSomething() { return 0; } // 输入参数不同,意味着方法签名不同,重载的体现 public int doSomething(Lis<String> srs) { return 0; } // return类型不一样,编译不能通过 public short doSomething() { return 0; }
面向对象设计原则
- 单一职责原则 , 类或者对象最好是单一职责,如果发现某个类中承担着多种义务,可以考虑拆分重构。
- 开闭原则,对扩展是开放的,但是对修改是关闭的。程序设计应保证平滑的扩展性,尽量避免因为新增同类功能而修改已实现。这样可以减少回归问题。(回归测试)。
- 里式转换原则, 进程继承抽象时,凡是可以用父类或者基类的地方,都可以用子类转换。简单的说,子类对象可以赋给父类对象,但父类对象不能赋值给子类对象。
- 接口分离原则,在进行类和接口设计时,如果在一个接口中定义了太多方法,子类可能只需要实现其中部分方法,这样就破坏了程序的内聚性,可采用接口分离方式,进行解耦。这样实现了高内聚,低耦合。
- 依赖反转,实体应该依赖于抽象而不是实现。也就是说,高层次模块,不应该依赖低层次模块。而是基于抽象接口。抽象接口不应该依赖具体,而具体要依赖于抽象。
interface Coder { void wearSweater(Sweater sweater); } class XiaoMing implements Coder{ @Override public void wearSweater(Sweater sweater) { } } interface Sweater { } class TneckSweater implements Sweater { } Coder xiaoming = new XiaoMing(); Sweater tneckSweater = new TneckSweater(); xiaoming.wearSweater(tneckSweater);
开闭原则改造如下代码:
public class VIPCenter { void serviceVIP(T extend User user>) { if (user insanceof SlumDogVIP) { // 穷X VIP,活动抢的那种 // do somthing } else if(user insanceof RealVIP) { // do somthing } // ... }
修改关闭,扩展开放的原则:
public class VIPCenter { private Map<User.TYPE, ServiceProvider> providers; void serviceVIP(T extend User user) { providers.get(user.getType()).service(user); } } interface ServiceProvider{ void service(T extend User user) ; } class SlumDogVIPServiceProvider implements ServiceProvider{ void service(T extend User user){ // do somthing } } class RealVIPServiceProvider implements ServiceProvider{ void service(T extend User user) { // do something } }