Java抽象类和接口的区别

抽象类

  • 概述

    1. 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的。类是对 对象的抽象,而抽象类就是对类的抽象。用来捕捉子类的通用特性 ,用来创建继承层级里子类的模板。

    2. 抽象类和普通类的区别是不能实例化和可以包含抽象方法(如果没有抽象方法就没有存在的意义)

    3. 由于抽象类不能实例化对象,所以抽象类必须继承后,才能使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。(子类必须重写父类的抽象方法,除非也是抽象类)

  • 为什么要用抽象类?
    普通类里定义的方法,子类也可以覆盖重写,为什么要定义成抽象类呢?
    当然是可以把抽象类都写成非抽象类的。但是现实中有些父类中的方法体确实没有必要写,因为各个子类中的这个方法肯定会有不同 (比如Dog 这个类的 eat 方法),所以没有必要在父类里写。而写成抽象类,这样别人看到你的代码,或你看到别人的代码,你就会注意抽象方法,而知道这个方法是在子类中实现的,所以,有个 提示作用
    总结:
    作用1:架构明确,清晰直观
    作用2:提示作用,重点关注

  • abstract 关键字
    用 abstract 修饰的类为抽象类,方法则为抽象方法。抽象方法不写 { } 括号。

    //抽象类
    abstract class Dog {
    	public abstract void sleep();
        public abstract void eat();
    }
    //具体类
    public class Poodle extends Dog{
        @Override
        public void eat() {
            System.out.println("Poodle吃罐头");
        }
        @Override
        public void sleep() {
            System.out.println("Poodle睡床");
        }
    }
    ---*---
    演示类
    

    抽象类和普通类的区别是可以有抽象方法,所以这里仅用抽象方法演示。将Dog定义为抽象类,有sleep和eat两个抽象方法。具体的狗Poodle(贵宾犬),再去实现这两个方法

  • 总结

    1. 抽象类不能被实例化

    2. 有抽象方法的类必定是抽象类。

    3. 抽象类中的抽象方法只是声明,不包含方法体。

    4. 构造方法,类方法(用 static 修饰的方法)、final方法、私有方法,不能声明为抽象方法。

    5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。


接口

  • 概述
    官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
    个人理解:接口可以理解为一种特殊的抽象类,其只能有公共的静态常量和公共的抽象方法(JDK 8之前)。接口是用来弥补Java类只能单继承,和在不影响原有继承体系情况下针对行为的扩展。比如飞行这个行为,鸟类可以实现,飞机类也可以实现。

  • 定义与实现 interface & implements

    //飞接口
    interface Fly{
        void fly();
    }
    //抽象鸟类
    abstract class Bird{
        abstract void eat();
        abstract void sleep();
    }
    //猫头鹰类
    class Owl extends Bird implements Fly{
        @Override
        void eat() {
            System.out.println("猫头鹰吃老鼠");
        }
    
        @Override
        void sleep() {
            System.out.println("猫头鹰睡树上");
        }
    
        @Override
        public void fly() {
            System.out.println("猫头鹰式飞行");
        }
    }
    ---*---
    演示类
    

    这里主要说一下为什么不把fly方法写到Bird类中。因为有一些鸟类是不会飞行的,但是它们至少是需要吃饭和睡觉的。所以这里我把eat和sleep方法写到了Bird抽象类,把fly写到一个接口。

  • 接口的特性
    1.接口都是abstract隐性修饰的
    2.接口没有构造方法,所以也就不能实例化(通过子类实例化)
    3.接口中只有静态常量(所有变量都以 public static final 隐性修饰)
    4.接口中的都是公共抽象方法(方法都以 public abstract 隐性修饰),在JDK8 之前
    5.接口可以多继承,而且一个类可以实现多个接口


区别

先来举一个简单的例子:

狗都具有 eat() 、sleep() 方法,我们分别通过抽象类和接口定义这个抽象概念

//通过抽象类定义
  public abstract class Dog {
      public abstract void eat();
      public abstract void sleep();  
  }
  
  //通过接口定义
  public interface Dog {
      public abstract void eat();
      public abstract void sleep();
  }

但是我们现在如果需要让狗拥有一项特殊的技能——钻火圈 DrillFireCircle(),如何增加这个行为呢?

思考:

  1. 将钻火圈方法与前面两个方法一同写入抽象类中,但是这样的话,但凡继承这个抽象类狗都具有了钻火圈技能,明显不合适
  2. 将钻火圈方法与前面两个方法一同写入接口中,当需要使用钻火圈功能的时候,就必须实现 接口中的eat() 、sleep() 方法(重写该接口中所有的方法)显然也不合适

那么该如何解决呢 ? 我们可以仔细想一想,eat和sleep都是狗本身所应该具有的一种行为,而钻火圈这种行为则是后天训练出来的,只能算是对狗类的一种附加或者延伸, 两者不应该在同一个范畴内,所以我们考虑将这个单独的行为,独立的设计一个接口,其中包含DrillFireCircle()方法, Dog设计为一个抽象类, 其中又包括eat() 、sleep() 方法.

一个SpecialDog即可继承Dog类并且实现DrillFireCircle()接口
下面给出代码:

//定义接口,含有钻火圈方法
  public interface DrillFireCircle() {
      public abstract void drillFireCircle();
  }//定义抽象类狗类
  public abstract class Dog {
      public abstract void eat();
      public abstract void sleep();
  }
   
  //继承抽象类且实现接口
  class SpecialDog extends Dog implements drillFireCircle {
      public void eat() {
        //....
      }
      public void sleep() {
        //....
      }
      public void drillFireCircle() () {
        //....
      }
  }
  • 总结
    继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如狗是否能钻火圈,能则可以实现这个接口,不能就不实现这个接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值