抽象类和接口的哲学设计思想

  不知道其他人是否有这样的疑惑,做了很久的java开发,对于接口和抽象类的语法使用也是了如指掌。但似总觉得对它没有彻底的搞明白,比如,笔者就有这样的疑惑:

  1.接口和抽象类都是作为抽象来使用的,为什么不单独使用接口或者单独使用抽象类?两者都存在的意义是什么?

  2.一个类为什么可以实现多个接口而不能继承多个抽象类?

  3.对于一个具体的业务,该使用接口还是该使用抽象类?

  基于以上问题,笔者也是网上找了大量的资料,其大部分都是在讲语法的使用及两者语法层面上的区别。说的也基本都对,但不是很全面。直到看到一位java大神的文章里的一句话“编程语言的设计其实也是一门哲学”,笔者道行浅显,还不能理解其深意,但是已是心潮澎湃,于是有了上面的标题。至于是否存在哲学思想,通过本文,各自自行体会。为了能将上面的问题说清楚,下面还是从最基本的语法开始。(jdk1.8

一 .接口

1.定义

  官网地址:https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html

  里面有这么一段:

Interfaces in Java

  In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces. Extension is discussed later in this lesson.

  谷歌翻译过来大概是:在Java编程语言中,一个接口是一个引用类型,类似于类,它可以包含常量,方法签名,默认的方法,静态方法和嵌套类型。方法主体仅适用于默认方法和静态方法。接口无法实例化-它们只能由类实现或由其他接口扩展

2.语法规范

  上面概念比较笼统,结合笔者经验,一步步将接口的使用方法用下面代码展示,为了时例子具有说明性,就以jdk自带的集合来说明。

  2.1 接口的定义

        

  接口定义比较简单,只需要 interface 关键字即可,如Map集合。List集合等。

  2.2 接口中方法的定义:

  返回值类型+方法名(参数。。。),例如,List集合的方法。并且,方法是没有方法体的。即只能生命方法,不能实现方法。

  

   以上是规范的定义方式,官方规定,方法必须定义成public或abstract形式,且是默认的。可以用一个测试例子看下哪些是不规范的,如下:

  

       idea编译器会将无用的代码置为灰色,如上图,从图中可以看出,public和abstract是可以省略的,且很多公司规则必须省略,如果将方法定义成private或者protected会直接语法报错。对于方法 size3(),虽然语法没有报错,但是由于静态方法不能被重写这一特性,在接口中定义静态方法是没有实际意义的。

  2.3 接口中常量的定义

  java规范:接口中不能定义变量,只能定义常量,格式:public static final 数据类型 常量名称(大写) = 数据值;且必须赋初始值。public static final 可省略。如下:

       

       

     如上图,由于接口中只能定义常量,所以必须赋初始值,不赋值,会报错。且 public static final 可省略。

  2.4 接口的实现:implements、extends

  (1)普通类实现接口

  

   如上,HashSet 类 实现Set接口,使用implements关键字,需重写接口中的所有方法,包括接口父接口的所有方法。上面HsahSet接口实现了Set接口中的所有方法和Coneable接口中的所有方法。如果 Set接口和Coneable接口有相同的方法,只需要重写一个。

  (2)接口实现接口

  接口实现接口需要使用extends关键字,不能使用implements。

  

   抽象类实现接口,可以重写接口中的方法,但不是必须重写。使用关键字implements。相反,抽象类是不能被接口继承的,因为,抽象类可以有具体的方法体,而接口不能。

二 .抽象类

1.定义

  官网地址:https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

  描述:

Abstract Methods and Classes

  An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.

  An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon)

谷歌翻译过来大概是

  一个抽象类是声明的类abstract-它可能会或可能不包括抽象方法。抽象类不能被实例化,但是可以被子类化。

  一个抽象方法是没有实现声明(没有括号,并且随后是分号);

  这个描述比较模糊,下面详细说明。

2.语法规范

    下面以java IO 流的源码展示。

  2.1 抽象类的定义

  

    定义只需要在普通类中增加 abstract 关键字即可。或者只要有抽象方法的类,肯定是抽象类。

  2.2 抽象类方法的定义

  

  抽象类中定义抽象方法,必须加关键字 abstract,并且方法没有方法体。构造方法和静态方法(类方法)不能定义为抽象方法。访问类型可以是public,protected,并且默认是public abstract类型。

  

  抽象类中定义普通方法,必须有方法体,和普通类中的方法定义一致。

  2.3 常量和变量的定义

  抽象类和普通类在定义常量和变量没有什么区别,如下图:

         

  2.4 抽象类的继承

  抽象类可以实现接口

  

     如上图,为Reader类对 Readable和 Closeable接口的实现。 抽象类实现接口,不必重写接口中的方法,但是,抽象类的子类必须重写接口以及抽象类中的抽象方法。

  普通类继承抽象类

  

   普通类继承抽象类,需要重写抽象类的所有抽象方法。

三 .异同

1.语法异同

  • 两者都是java多态的体现;
  • 两者都不能实例化 ( 抽象类即使有构造方法也不能实例化 );
  • 两者都需要通过子类实现或继承使用;
  • 接口中不能有构造方法,抽象类可以有构造方法;
  • 接口中不能包含静态方法,抽象类中可以包含静态方法;
  • 接口定义使用implements,抽象类使用extends关键字;
  • 接口子类可以实现多个接口,抽象类子类只能继承一个父类;
  • 接口中只能有抽象方法,并且没有方法体。抽象类中可以有普通方法,也可以有抽象方法,抽象方法没有方法体;
  • 接口的实现类必须重写接口的所有方法,抽象类的子类需要重写父类的抽象方法;
  • 接口中只能定义常量,且修饰符必须是public static final,可省略,抽象类和普通类的成员变量定义没有区别;
  • 接口中的方法默认为public abstract类型,抽象类的抽象方法必须为public或者protected,缺省情况下默认为public

2.设计思想异同

  • 都是抽象的概念,是对上层的一种抽象,不能具体的描述一个具体的对象;
  • 接口是对行为的抽象,比如鸟有飞的行为,也有吃的行为。可以将“吃”和“飞”这两个动作分别封装在两个接口的两个方法中,不同具体的鸟可能具有多种特性,去实现这两个接口,所以一个类可以实现多个接口,因为它可能具有多种特性,即接口说的是 “有没有”的特性;
  • 抽象类是对事物的抽象或者说是对根源的一种抽象,比如说把“人”作为抽象类,男人抽象类和女人抽象类,一个具体的人作为子类,子类只能继承一个抽象类,因为没有人既是男人,又是女人,因此,抽象类只能是单继承,即抽象类说的是 “是不是”的特性;
  • 接口不对具体的事物或者具体的对象描述,抽象类是对事物的一种高度的抽象。接口是比抽象类更为抽象的一种抽象;
  • 接口设计是为了代码的扩展性和隔离性,也就是设计模式中“依赖倒置原则”的要求,开发者需要面向接口编程而非面向实现编程;
  • 抽象类设计是为了代码的复用性,将多个事物的共同属性抽象到一个抽象类中,减少代码的冗余

能想到的只能是上面这些了~~~

原文地址:https://www.cnblogs.com/xyzyj/p/9497376.html