zoukankan      html  css  js  c++  java
  • 抽象类与接口

    抽象类与接口是java语言中对抽象概念进行定义的两种机制。

    在面向对象领域由于抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类和接口都是不能实例化的。

    一、抽象类

    抽象类体现了数据抽象的思想,是实现多态的一种机制。它定义了一组抽象的方法,至于这组抽象方法的具体表现形式,由派生类来实现。同时抽象类提供了继承的概念,它的出发点就是为了继承,否则它没有存在的任何意义。所以说定义的抽象类一定是用来继承的。

    只要包含一个抽象方法的抽象类,就必须要定义成抽象类

    抽象类中可以包含具体的方法,当然也可以不包含抽象方法。

    子类中的抽象方法不能与父类的抽象方法同名。

    abstract不能与final并列修饰同一个类。——final类无法被继承,而abstract类就是为了有子类继承的。

    abstract 不能与private、static、final或native并列修饰同一个方法。

    创建抽象类和抽象方法非常有用,因为他们可以使类的抽象性明确起来,并告诉用户和编译器打算怎样使用他们.抽象类还是有用的重构器,因为它们使我们可以很容易地将公共方法沿着继承层次结构向上移动。

    二、接口

    接口是抽象类的延伸,java为了保证数据安全是不能多重继承的,也就是说继承只能存在一个父类,但是接口不同,一个类可以同时实现多个接口,不管这些接口之间有没有关系,所以接口弥补了抽象类不能多重继承的缺陷,但是推荐继承和接口共同使用,因为这样既可以保证数据安全性又可以实现多重继承。

    接口是用来建立类与类之间的协议,它所提供的只是一种形式,而没有具体的实现。同时实现该接口的实现类必须要实现该接口的所有方法,通过使用implements关键字,他表示该类在遵循某个或某组特定的接口

    一个Interface的所有方法默认是public abstract的。声明为protected和private会编译报错。

    Interface中的成员变量默认是public static final的。

    可以使用 instanceof 检查一个对象是否实现了某个特定的接口。

    在实现多接口的时候一定要避免方法名的重复。

    三、区别

    3.1 语法层次

    【声明和定义】抽象类与普通类比较类似,在定义class时加上abstract修饰。而接口完全不是类的概念,定义时使用interface关键字。

    【权限修饰符】抽象类允许使用可见型权限修饰符(除了private以外的权限修饰符)。而接口只能用public或包访问权限,且默认是abstract。

    【继承和实现】抽象类是用来继承的(extends),子类继承抽象类可以实现部分或全部抽象方法,只要还有一个抽象方法,该类就仍然是抽象类,不能被实例化。接口是用来实现的(implements),实现类必须实现接口内的全部方法。只能接口继承接口,类不能继承接口。

    【关于方法】抽象方法只需声明,不需实现。抽象类中可以有抽象方法也可以有普通方法。接口中所有方法默认都是抽象的。抽象类中的抽象方法,权限修饰不能使用private,其他都可以。接口中的方法权限修饰只允许为public或包访问权限。

    接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

    【关于成员变量】抽象类中和普通类一样,可以定义各种成员变量。但接口中定义的成员变量默认都是public static final的,一般也不会在接口中定义变量。

    image

    image

    image

    3.2 设计层次

    【抽象层次】笔者认为,接口比抽象类抽象得更彻底。抽象类可以看作是介于普通类和接口之间、约束没有那么严格的一种抽象形态。

    抽象类是对类的抽象,包括属性、行为。而接口是对行为的抽象。

    【跨域】由于抽象层次不同,接口的跨域相对于抽象类要宽泛得多。抽象类所跨域的是具体相似特点的类,而接口却可以跨域不同的类。因为接口抽象的是行为,与它的实现类之间不存在任何关系,只要实现类需要这样一个契约,就可以实现该接口。而抽象类位于继承体系中,本身就隐含了继承关系的约定。

    【设计层次】抽象类是自上而下的体系中的一环,一定是对继承体系有既定的公约的,譬如描述一个怎样的子类,有哪些共通之处。而接口只是一个规则,根本不需要知道子类的存在,子类到底是什么、怎么实现它不需要管。

    抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。

    抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。

    对于抽象类,如果需要添加新的方法,可以直接在抽 象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

    四、ISP(Interface Segregation Principle)接口分离原则

    如果类的接口定义暴露了过多的行为,则说明这个类的接口定义内聚程度不够好。换句话说,类的接口可以被分解为多组功能函数的组合,每一组都服务于不同的客户类,而不同的客户类可以选择使用不同的功能分组。

    【接口污染问题】如果:每当一个衍生类需要使用一个新的接口时,就把这个接口添加到它的基类中,这样就会造成接口污染。持续的污染将使得基类接口变得越来越臃肿。

    因为将一个新的接口方法添加到基类定义中,基类的所有其他衍生类都相应地增加了该方法。而事实上,不需要该方法的子类可能没有提供实现,而是直接使用了基类中的空实现。这样的设计违背了里氏替换原则,降低了代码的可维护性和可复用性。

    当客户类被强迫依赖那些它们不需要的接口时,则这些客户类不得不受制于这些接口。这无意间就导致了所有客户类之间的耦合。换句话说,如果一个客户类依赖了一个类,这个类包含了客户类不需要的接口,但这些接口是其他客户类所需要的,那么当其他客户类要求修改这个类时,这个修改也将影响这个客户类。通常我们都是在尽可能的避免这种耦合,所以我们需要竭尽全力地分离这些接口。

    [里氏替换原则] LSP: The Liskov Substitution Principle

    使用基类对象指针或引用的函数必须能够在不了解衍生类的条件下使用衍生类的对象。

    顶层接口不依赖于底层实现。

    【接口分离原则】"客户类不应被强迫依赖那些它们不需要的接口"。

    通过应用 Adapter 设计模式,采用委托(delegation)或多继承方式,胖接口可以被分离成多个抽象的基类接口,从而打破客户类之间的不必要的耦合。详见http://www.cnblogs.com/gaochundong/p/interface_segregation_principle.html

    五、面向接口编程

    主体构架使用接口,接口构成系统的骨架,这样就可以通过更换接口的实现类来更换系统的实现

    待补充

    参考资料

    http://blog.csdn.net/chenssy/article/details/12858267

    https://yq.aliyun.com/articles/32108

    http://www.cnblogs.com/gaochundong/p/interface_segregation_principle.html

    http://www.cnblogs.com/gaochundong/p/liskov_substitution_principle.html

  • 相关阅读:
    WCF 第八章 安全 确定替代身份(中)使用AzMan认证
    WCF 第八章 安全 总结
    WCF 第八章 安全 因特网上的安全服务(下) 其他认证模式
    WCF Membership Provider
    WCF 第八章 安全 确定替代身份(下)模仿用户
    WCF 第八章 安全 因特网上的安全服务(上)
    WCF 第九章 诊断
    HTTPS的七个误解(转载)
    WCF 第八章 安全 日志和审计
    基于比较的排序算法集
  • 原文地址:https://www.cnblogs.com/lddbupt/p/5733841.html
Copyright © 2011-2022 走看看