手记

Java中的抽象类与接口(1)

Java是一种纯面向对象的编程语言类和对象是它的两个基本语言特性学过Java的人都应该知道但它还有另外两个比较容易搞混淆的特性抽象类和接口

我尝试着结合自身的经验把这个问题搞清楚受个人经验能力所限出现纰漏在所难免欢迎来辩

先看一张表(《Java编程思想中列出的关键特性):

 


拿一个实际的问题举例

所有的生物都有“吃东西”和“繁衍后代”这样的共性接口哺乳类动物具有胎生、肺呼吸、体温恒定等共性,这就可以用抽象类来表示这样就不必与生物这个基类紧耦合代码表示如下

/**
 * 生物
 *
 */
public interface Bios {
   /**
    * 吸收能量
    */
   public void energy();

   /**
    * 繁衍
    */
   public Object multiply();
}
 
/**
 * 动物
 *
 */
public interface Animal extends Bios {
   /**
    * 移动
    */
   public void move();

   /**
    * 吃东西
    */
   public void eat();
}
 
/**
 * 哺乳纲
 *
 */
public abstract class Mammal implements Animal {
   /**
    * 体温恒定
    */
   protected static double temperature = 37;

   /**
    * 胎生
    */
   public abstract Object vivipation();

   /**
    * 肺呼吸
    */
   public abstract void pulmonary();
}
 
/**
 * 灵长类
 *
 */
public abstract class Primate extends Mammal {
   /**
    * 偶蹄,蹄均呈双数
    */
   protected static boolean evenHoof = true;

   /**
    * 大脑发达,会思考
    */
   public abstract void thinking();
}
 
/**
 * 人类
 * 生物 -> 动物 -> 哺乳纲 -> 灵长目
 *
 */
public class Person extends Primate {
   @Override
   public void move() {
      // TODO Auto-generated method stub
   }

   @Override
   public void eat() {
      // TODO Auto-generated method stub
   }

   @Override
   public void energy() {
      // TODO Auto-generated method stub
   }

   @Override
   public Object multiply() {
      // TODO Auto-generated method stub
      return null;
   }

   @Override
   public void thinking() {
      // TODO Auto-generated method stub
   }

   @Override
   public Object vivipation() {
      // TODO Auto-generated method stub
      return null;
   }

   @Override
   public void pulmonary() {
      // TODO Auto-generated method stub
   }
}


可以看到,「人类继承了哺乳纲灵长类的属性同时也需要实现生物」、「动物接口和哺乳纲」、「灵长类的抽象方法

至于抽象类和接口的区别很多技术博客都写过比如有些博主写得很好比如门和报警器的例子鸟和飞机的例子不过在我看来这都是从语言本身的特性来说明两者的区别如果换一种例子换一个场景恐怕又会懵圈——好像什么都说了又好像什么都没说

与其将语法解释的很明白倒不如把它用明白这其实就是新手和高手之间的最大区别新手总想弄懂每一招每一式但高手更注重肌肉记忆所产生的反馈循环什么意思呢

来看看好的实践是怎么用抽象类和接口的吧

 


这是Java I/O中的类继承结构图这只是一部分但用说明问题已经足够了

可以看到AbstractList是一个抽象类,实现List接口,List接口又继承自Collection接口

抽象类AbstractList的部分定义是

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    ......
    public abstract E get(int index);
    ......
}


接口List的部分定义是

public interface List<E> extends Collection<E> {
    ......
    E get(int index);
    ......
}


同样可以很清楚地看到抽象类和接口中都定义了E get(int index)这个方法这是为啥而且这个方法还是抽象类唯一的方法为了这个方法单独定义一个抽象类因为作用不同

接口中的E get(int index)是一种获取列表元素的操作List这个接口集中了所有对列表可能的操作

确切地来说抽象类的更像是一种模板」,规定了它的子类需要干的工作而接口更像是一种约束」,只要实现了接口的类都要实现接口的方法而且这种约束是可以不断往下传递的——只要父类有了这种约束那么子类也全都得遵守这种约束如果这个约束被修改了那么遵守它的类也全都要跟着修改

所有的集合都要能够迭代可增加删除和获取元素这就是一种约束所以以接口形式表现而不同类型的集合又有不同类型的方法有些方法不需要工程师自己实现仅仅可以作为默认的模板提供而模板是不需要实例化的也最好禁止实例化所以它只能是抽象的不能具体化抽象类本身也是可以没有抽象方法的)。

所以多看一些优秀的源码JDK的源码Spring的源码多揣摩作者的设计意图看多了也就慢慢会了

 


0人推荐
随时随地看视频
慕课网APP