abstract与interface的区别

296 阅读3分钟

题记

今天在尝试看源码,但是发现好多abstract,虽然明白abstract是怎么用的,但是总觉得他和interface应用起来实际没太大区别。就在刚刚想明白了一些。

先拿ReentrantLock举例子

声明

public class ReentrantLock implements Lock, java.io.Serializable

内部类

abstract static class Sync extends AbstractQueuedSynchronizer

AQS

public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable 

可以看到源码中abstract用的很多

个人看法

我认为啊,abstract更多的就是为了限制你,让你选择正确的上层,并且不能摇摆。而interface可以多元化的选择。

先上一下文字定义

1.相同点

A. 两者都是抽象类,都不能实例化。
B. interface实现类及abstrctclass的子类都必须要实现已经声明的抽象方法。

2. 不同点

A. interface需要实现,要用implements,而abstract class需要继承,要用extends。
B. 一个类可以实现多个interface,但一个类只能继承一个abstract class。
C. interface强调特定功能的实现,而abstractclass强调所属关系。
D. 尽管interface实现类及abstrct class的子类都必须要实现相应的抽象方法,但实现的形式不同。interface中的每一个方法都是抽象方法,都只是声明的(declaration,没有方法体),实现类必须要实现。而abstractclass的子类可以有选择地实现。

例子

比如我们想养只狗,不想养猫,那这时候我们定义一个抽象类的狗,继承狗就可以了。这样既可以保证狗的多态(泰迪、柯基、哈士奇),又能直观的知道这是狗,不是猫。我还想规定,作为狗你要是想跑,我给你提供一个你可以参考的跑的方法。

先做关于狗的限制

创建抽象的狗类

// 想限制的方法上也需要加abstract
public abstract class AbstractDog {

    public abstract void eat();
}

创建哈士奇的类,继承狗类

public class HaShiQi extends AbstractDog{



    public static void main(String[] args) {
        HaShiQi haShiQi = new HaShiQi();

        haShiQi.eat();
    }

    @Override
    public void eat() {
        System.out.println("哈士奇专属狗粮");
    }
    

}

运行结果:哈士奇专属狗粮

增加实现

现在虽然限制了作为狗,吃只能吃狗粮,但是作为动物,他们都可以睡觉,作为宠物,他们都会有主人,所以这时候可以再定义两个接口类

创建动物的接口类

public interface Animal {

    void sleep();
}

创建宠物的接口类

public interface Pet {

    void master();
}

HaShiQi 实现 Animal 和 Pet 接口

public class HaShiQi extends AbstractDog implements Animal,Pet{



    public static void main(String[] args) {
        HaShiQi haShiQi = new HaShiQi();

        haShiQi.eat();
        haShiQi.sleep();
        haShiQi.master();
    }

    @Override
    public void eat() {
        System.out.println("哈士奇专属狗粮");
    }


    @Override
    public void sleep() {
        System.out.println("二哈的睡觉姿势");
    }

    @Override
    public void master() {
        System.out.println("二哈的主人--" + Thread.currentThread().getName());
    }
}

输出结果

哈士奇专属狗粮\
二哈的睡觉姿势\
二哈的主人--main

Process finished with exit code 0

狗类增加跑的方法

public abstract class AbstractDog {

   public abstract void eat();

   public void run(){
       System.out.println("我可以时速800m");
   }
}

main方法增加调用

public static void main(String[] args) {
    HaShiQi haShiQi = new HaShiQi();

    haShiQi.eat();
    haShiQi.sleep();
    haShiQi.master();
    // 调用新加的run方法
    haShiQi.run();
}

输出结果 哈士奇专属狗粮 二哈的睡觉姿势 二哈的主人--main 我可以时速800m

Process finished with exit code 0

感叹一下

做了这么多年业务开发,感觉是个老程序员了,回过头去再看看当时的基础性的东西,发现还差得远。本篇文章只是我个人的看法,如果有不正确欢迎指点。