zoukankan      html  css  js  c++  java
  • java面向对象--抽象类和接口

    如果某个父类只知道其子类应该包含哪些方法,但无法知道如何实现这些方法,同时要使用多态的特性,怎么办?

    抽象方法:关键字abstract允许在一个类中创建一个或多个没有方法体的方法——只提供方法签名,但没有相应的具体实现(不是空方法体)。

    包含抽象方法的类只能被定义为抽象类,但抽象类可以没有抽象方法,只是为了不被实例化。

    抽象类可以包含成员变量、方法(抽象或具体)、构造器和初始化块等,但不能被实例化,只能被当作父类被其他子类继承。

    子类必须实现所有父类/接口的抽象方法,除非当前类也是抽象类。

    抽象类的作用:从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。

     

    接口:定义某一批类所需要遵循的公共行为规范,所有实现了该特定接口的类都具有相同的功能。接口只提供了形式,而未提供任何具体实现,是对动作的抽象。

    接口可以是public或默认的包访问权限,如果是public的,源文件名需和接口名相同。

    接口中的方法默认为public abstract,成员变量默认是public、static 和 final 的常量。

    类实现接口里的方法时只能使用public访问限定符。

    接口不仅可以继承,而且可以同时继承多个接口,多个interface用’,’隔开。

    使用接口的核心原因:为了能够向上造型为多个父类型,面向接口编程。

    多重继承:java中不能同时继承多个类,但可以通过组合继承一个类和实现多个接口实现伪多重继承。

    优先使用类而不是接口。

    接口与抽象类的区别: 

    接口作为系统和外界交互的窗口,接口体现的是一种规范。对于接口的实现者而言,接口规定了实现者必须向外提供哪些服务(以方法的形式来提供);对于接口的调用者而言,接口规定了调用者可以调用哪些服务,以及如何调用这些服务(就是如何来调用方法)。当在一个程序中使用接口时,接口是多个模块间的耦合标准;当在多个应用程序之间使用接口时,接口是多个程序之间的通信标准。

    从某种角度上来看,接口类似于整个系统的“总纲”,它制定了系统各模块之间应该遵循的标准,因此一个系统中的接口不应该经常改变。一旦接口改变,对整个系统而言甚至其他系统的影响将是辐射式的,导致系统中的大部分类都需要改写。所以,在一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。

    抽象类则不一样,抽象类作为系统中多个子类的共同父类,它所体现的是模板式设计。抽象类作为多个子类的的抽象父类,可以被当成系统实现过程中的中间产品,这个产品已经实现了系统的部分功能(那些在抽象类中已经提供实现的方法),但这个产品依然不能当成最终产品,必须有更进一步的完善。

    除此之外,接口和抽象类在用法上也存在如下区别: 

    接口里只能包含抽象方法,抽象类则可以包含普通方法。 

    接口里不能定义静态方法,抽象类里可以定义静态方法。 

    接口里不包含构造器,抽象类可以包含构造器。抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。

    接口里不能包含初始化块,但抽象类可以包含初始化块。

    接口里只能定义静态常量,抽象类既可以定义普通变量,也可以定义静态常量。 

    接口可以可以继承多个接口,类只能继承一个类。

    抽象类主要是用来抽象类别,接口主要是用来抽象方法功能。当关注事物的本质时,使用抽象类,当关注一种操作时,使用接口。

    工厂模式

    接口体现的是一种规范和实现分离的设计哲学,面向接口编程而不是面向实现类编程,可以降低程序个模块之间的耦合,提高系统的可扩展性和可维护性。

    通过工厂方法,接口和实现完全分离,可以非常方便的更改实现。

    interface Service // Service接口,可以有多种实现
    {
       void method1();
       void method2();
    }
    
    interface ServiceFactory // 工厂接口,可以由多种实现
    {
       Service getService();
    }
    
    class Implementation1 implements Service {  //Service接口的实现1
       public Implementation1() {  }
       public void method1() {
          System.out.println("Implementation1 method1");
       }
       public void method2() {
          System.out.println("Implementation1 method2");
       }
    }
    
    class Implementation1Factory implements ServiceFactory{ //生成对象1的工厂1
       public Service getService() {
          return new Implementation1();
       }
    }
    
    class Implementation2 implements Service {  // Service接口的实现2
       public Implementation2() {  }
       public void method1() {
          System.out.println("Implementation2 method1");
       }
       public void method2() {
          System.out.println("Implementation2 method2");
       }
    }
    
    class Implementation2Factory implements ServiceFactory{//生成对象2的工厂2
       public Service getService() {
          return new Implementation1();
       }
    }
    
    public class Factories { //使用service的模块
       public static void serviceConsumer(ServiceFactory fact) {
          Service s = fact.getService(); //向上造型,工厂将生成某类实现接口的对象
          s.method1();
          s.method2();
       }
       public static void main(String[] args) {
          serviceConsumer(new Implementation1Factory());
          //serviceConsumer(new Implementation2Factory());很方便就可以更改实现
       }
    }

     

  • 相关阅读:
    Java启动工程时,加载固定数据到Map中(不用每次访问数据库)
    Java删除文件夹和其子文件、文件的拷贝和剪切
    EasyExcel导入工具(SpringMVC下使用)
    web工程启动时,在一个类中延迟加载Bean,因为该Bean类可能还没被JVM加载
    ECharts访问后台,JSON格式返回数据实例
    Java 实现缓存,一个线程存,一个线程取
    IE浏览器使用VLC实时显示视频(海康、大华)
    Windows和Linux下 Java开发ping工具类
    Quartz定时器+Spring + @Autowired注入 空指针异常
    ubuntu 安装mysql
  • 原文地址:https://www.cnblogs.com/kevin2chen/p/6689015.html
Copyright © 2011-2022 走看看