首页 > 编程知识 正文

抽象类和接口的应用场景,接口与抽象类有哪些共同点

时间:2023-05-05 03:39:08 阅读:276102 作者:4242

原文链接:https://blog.csdn.net/Sun_flower77/article/details/78019957 

1.接口特性 
2. 抽象类和接口的区别以及使用场景 
3. 为什么要使用接口

- 接口的特性:

接口不是类,不能使用new运算符实例化一个接口,但是可以声明接口的变量,这个接口变量必须引用实现了接口的类对象
使用instanceof可以检查一个对象是否属于某个特定类,也可以使用它来检查一个对象是否实现了某个特定的接口
接口可以被扩展,即一个接口可以继承另一个接口
在接口中不能包含实例域或静态方法,也不能在接口中实现方法,但却可以包含常量
接口中的方法自动地被设置为public abstract,接口中的域被自动设为public static final。虽然在接口中可以让方法省略public,但是在具体实现类必须加上public

interface demo{ static int d(){ return 0; }}


java8接口新特性(针对以上第四点)

1. 可以有静态方法,但必须去实现它

interface demo{ default int d(){ return 0; }}


由于java可以同时实现多个接口(接口与接口之间使用逗号隔开),如果一个类同时实现了多个接口,而这几个接口中同时存在同名、同参数的静态方法,使用实现类去调用接口中的静态方法,将不知道具体调用哪一个。所以,java拒绝使用“实现类.接口静态方法”,只能使用“接口.接口静态方法”去访问。由于在实现类中也可以定义与接口中同名同参的静态方法,但是不能用@Override修饰,所以接口中的静态方法不能被重写

2. 可以有default方法,且必须去实现它

interface demo{    default int d(){        return 0;    }}


实现类可以去重写接口中default方法,但必须显式加上public,去掉default,因为default关键字只能出现在接口中

看到这里,对接口的特性已经有了一定的了解。你可能会有这么几个困惑:

1. 接口跟抽象类有什么区别呢?

语法上的一些区别就不说了,什么抽象类可以有构造器,接口不能有构造器啊什么的,说了也没多大实际意义。我就说一下他们存在的意义和适用的场景。

其实这并没有什么标准答案,每个人的理解都不同,都是根据自己实际做项目的经验总结出来的,每一种理解都是可以相互借鉴的。

接口带来的最大好处就是避免了多继承带来的复杂性和低效性,并且同时可以提供多重继承的好处。接口和抽象类都可以体现多态性,但是抽象类对事物进行抽象,更多的是为了继承,为了扩展,为了实现代码的重用,子类和父类之间体现的是is-a关系;接口则更多的体现一种行为约束,一种规则,一旦实现了这个接口,就要给出这个接口中所有方法的具体实现,也就是说实现类对于接口中所有的方法都是有意义的。

举个列子,现在要定义一个猫类和一个危机的洋葱,你可以直接定义两个类

class Cat{    private String color;    private String name;    public void shout(){        System.out.println("喵喵喵");    }    public void eat(){        System.out.println("吃饭啦");    }}class Dog{    private String color;    private String name;    public void shout(){        System.out.println("汪汪汪");    }    public void eat(){        System.out.println("吃饭啦");    }}


这样设计完全可以,但是当某一天又要设计一个猪类呢,是不是又要重复以上的代码,这样是不利于代码的重用的,我们看到猫类和危机的洋葱都有名字和颜色属性,都有吃和叫这两个行为,那么是不是可以抽象出一个公共基类呢,这个公共基类和这些动物类的关系明显是is-a关系。由于猫和狗叫的方式不同,所以这个类不能是普通的类,只能是抽象类

abstract class BaseAnimal{    private String color;    private String name;    public abstract void shout();    public void eat(){        System.out.println("吃饭啦");    }}class Cat extends BaseAnimal{    public void shout(){        System.out.println("喵喵喵");    }}class Dog extends BaseAnimal{    public void shout(){        System.out.println("汪汪汪");    }}


很明显这样实现了代码的重用,以后要设计一个猪类,只要继承BaseAnimal类并实现shout方法就可以了,而不用写那么多重复的代码,那么能不能把BaseAnimal定义成接口呢,而不是抽象类?肯定是不行的,先不说接口中不能定义color和name这两个域,即使这些动物只有行为没有属性,也是不能把BaseAnimal定义成接口的,这些动物都有一个共同的行为,就是吃饭,每个实现类都去实现一遍相同的代码是没有意义的。如果定义为接口,那么Cat类和Dog类是没办法扩展的,实现类要想扩展只能改变接口,但是接口和抽象类一旦定义好,是不会轻易修改的,除非修改的内容对于实现类或者继承这个抽象类的类是有意义的,因为接口和抽象类设计出来作为被公共使用的对象,你不会知道有多少人在使用这个接口或者抽象类,一旦修改接口或抽象类,势必要惊动使用者,而修改的内容,使用者也不一定能用到。抽象类就明显不同了,要想扩展猫类,直接修改猫类就行了,而危机的洋葱完全不受影响。

之前我们说了,接口是一种约束和规则,一旦实现了某个接口,就必须实现这个接口中所有的方法,且这些方法对于这个类都是有意义的。现在定义一个接口,接口中有两个方法,一个方法可以比较,一个方法显示动物的技能。当需要设计一个既可以比较又有技能的动物类时,只要实现这个接口,那就必定要实现这两个方法。没有接口,你可能设计出来的动物类只有技能,而忘了能比较这个功能。所以说,接口就是一份契约,由类实现契约。契约中我编写了某些大的方针与前提,而签了约的类可以具体问题具体分析来实现自己的功能

在我们的项目中,为什么数据访问层和业务逻辑层用的是接口而不是抽象类,就是因为当有一个专门的人根据项目需求把接口设计好之后,下面的人就可以根据这份规则去实现接口,完成项目功能,下面的人不能随意扩展,也不需要去扩展,扩展只能交给设计接口的人。只要项目需求不变,接口是不需要改变的,如果经常变动接口,只能说明这个接口是设计的不合理的。

以后在考虑是使用接口还是使用抽象类的时候,只要根据自己实际的项目场景,根据这样设计的目的以及设计的合理性去选择。一般情况下,抽象类和接口是要同时使用的

2. 为什么要使用接口,方法的定义和实现都在一个类里完成不就行了?

我当初刚开始做java的时候,也是有这个困惑的,为什么非要整个接口出来,有个方法需要加个参数,就要先去改接口,再去改实现,本来只要改一个地方,现在要改两个地方,麻不麻烦。

这主要还是看你项目的复杂程度,项目团队的水平和人数。如果你的项目是你一个人在做,或者两三个水平差不多的人在做,一个功能,从业务逻辑到数据访问都可以由同一个人完成,那么使用接口的意义就不是很大,因为这种需求明确,业务不是很复杂的系统,一旦完成基本是不会怎么改了,用接口反而增大任务量,而且接口设计还是挺有难度的,设计接口对于抽象能力有很高的要求,如果要更改实现类,还要去更改接口,那么这个接口肯定是不合理的;相反的,如果你的业务比较复杂,系统比较庞大,就需要有一个抽象能力很高的人来专门设计这个接口,他可以忽略实现的细节,把精力更多的花在设计上,这样效率会更高。如果你的团队水平有高有低,那么也是需要设计一个接口来统一规范的。还有一种情况就是项目人员很庞大,项目提交容易出错的情况下,也是需要用到接口的
接口的另一大好处就是体现多态性,来实现系统的解耦,如果你的系统比较庞大,当项目上线后,数据量越来越大,对于性能的要求也越来越高,需要将原先的mysql换成oracle,或者需要将原生的jdbc换成herbinate,那么接口的好处就体现出来了,完全可以用herbinate新写一套实现,而不会惊动上层,上层业务逻辑层是丝毫不会察觉到你有任何变动的。
接口和实现类分离,分工协作,大大提高工作效率。设计接口的人专注于设计接口,这样的系统更能符合客户的需求;一个功能,写逻辑业务的程序员不必等到写数据访问的程序员写完才能开始写,他们可以同时进行,提高了工作效率。当然,不使用接口,就把所有的方法都设计好,具体实现代码让其他人去填也是可以的,但是这样不方便,也不规范。
千万不要为了使用接口而使用接口,一个小项目,mysql完全能在十年内都符合要求,别人问你为什么要用接口,你对他说,为了以后怎么样怎么样,万一需要把mysql换成oracle呢。但是如果这个万一一直没有发生,是不是这个项目就永远只有一套实现了,只有一套实现,那么解耦不解耦就根本体现不出。还不如一开始简单点,不用接口,等以后这个万一真的发生了,再重构就行了,毕竟ide重构也不是吃素的。
总的来说,还是看情况而定吧,没有一尘不变的硬性规定的。主要还是看你的项目和项目团队。
--------------------- 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。