Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-03-21:抽象类与接口的区别? #10

Open
Moosphan opened this issue Mar 21, 2019 · 29 comments
Open

2019-03-21:抽象类与接口的区别? #10

Moosphan opened this issue Mar 21, 2019 · 29 comments

Comments

@Moosphan
Copy link
Owner

No description provided.

@Moosphan Moosphan added the underway the daily question is solving now label Mar 21, 2019
@Ssuiyingsen
Copy link

1.抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。
2.接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。

@Moosphan
Copy link
Owner Author

Moosphan commented Mar 22, 2019

大体区别如下:

  • 抽象类可以提供成员方法的实现细节,而接口中只能存在 public 抽象方法;
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的;
  • 接口中不能含有构造器、静态代码块以及静态方法,而抽象类可以有构造器、静态代码块和静态方法;
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口;
  • 抽象类访问速度比接口速度要快,因为接口需要时间去寻找在类中具体实现的方法;
  • 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。如果你往接口中添加方法,那么你必须改变实现该接口的类。
  • 接口更多的为了约束类的行为,可用于解耦,而抽象类更加侧重于代码复用。

同时这里也抛出一个问题:日常SDK开发过程中如果直接更改接口函数可能会导致兼容性问题,一般情况下我们可以如何规避这个问题?

@Moosphan Moosphan added finished and removed underway the daily question is solving now labels Mar 22, 2019
@FeatherHunter
Copy link
Collaborator

Java不像C++一样能继承多个类,通过实现多个接口,能实现多继承的效果

@manondidi
Copy link

kotlin中interface 可以直接定义方法的实现,java8中也可以通过default关键字 来定义方法的实现,接口是可以定义方法的实现的,而且没有单继承的限制,推荐这么做

@Maskedheroe
Copy link

Java不像C++一样能继承多个类,通过实现多个接口,能实现多继承的效果

除了实现多个接口,亦可以通过内部类。

由于多继承会出现方法重名的歧义错误,但Iterface可以多继承,多个extends,这是由于它的实现类一定会实现其方法,所以它并不会发生重名错误。

@Moosphan
Copy link
Owner Author

@manondidi 不错,Java8之后interface被扩展了,感谢补充😉

:octocat: From gitme Android

@maoqitian
Copy link

Java接口和抽象类是什么,有什么区别
之前写过一篇文章,希望能有所补充

@Alex-Cin
Copy link

Alex-Cin commented Apr 5, 2019

楼上几位的回答, 非常赞啦!
1.. 但是我再补充一个问题, 为什么, 接口不可以有属性的声明, 只有方法的声明?
2.. 如果C类, 实现了A接口, 又实现了B接口, AB都有 print 方法, 请问这样可以吗?

@StefanShan
Copy link

@Alex-Cin 1.接口中是可以声明属性的,声明的属性默认都是public static final ,所以大家通过接口来替代Enum来实现枚举。2.C类实现A、B接口是可以的,只是编译器会提醒你实现的print方法为两个接口相同的方法而已,运行是可以的,因为主要逻辑还是在于你的C实现类。

@Alex-Cin
Copy link

Alex-Cin commented Apr 9, 2019

1.. 是我描述的不够严谨, 是普通属性(普通, 不用我多解释, 大家都明白的);
事实上我们不是用接口来代替枚举, 而是用 @inteface 来代替;

@StefanShan

@Moosphan Moosphan added Java and removed finished labels Apr 11, 2019
@wenyuan1104
Copy link

1、接口全是抽象方法可用作制定协议规范,变量全是final不可修改,即接口本身特性规定只能定义常量,接口是更高级更纯粹的抽象意义,体现了开闭原则:对修改关闭,对扩展开放。
2、抽象类的可以有抽象方法和具体实现所以扩展性比接口强。体现了复用共用性,父类新增一个方法,那么子类都拥有而不用去一一添加。

@ForgetSky
Copy link

Java抽象类和接口的异同: https://blog.csdn.net/u012216131/article/details/80389725

@scsfwgy
Copy link

scsfwgy commented Apr 25, 2019

看了回答,多说一点。在定义方法的参数的时候,形参定义为接口,实参交给实际调用者。这个规则交给方法定义者,实现交给调用者,会更加灵活。比如:一个方法void test(List params){params.add("xxx")} ,具体传递过来是ArrayList还是LinkedList由调用者决定,也就是内部算法也是调用者决定;而方法只执行接口的add方法。----- 也就对应的接口设计的理念:制定规则,具体实现交给实现者。

为什么说要面向接口编程,其实是为了你的程序提供更好的扩展性。�上述的例子只是一个很简单的demo,但是原理都是互通的。

@RedDargon
Copy link

1.抽象类跟接口都是为了抽取共性而存在的。
2.抽象类可以有实现方法 ,接口不可以(Java8可以 但是要求api过高 没啥用)
3.java是单继承多实现 所以一个类只能继承一个抽象类,但是可以实现多个实现类。
4.从理解上来讲抽象类 ,更多的是定性为一种类型 ,而接口则定义为一种功能 一种行为。
5.抽象类可以有构造方法跟静态方法/代码块 ,而接口不可以。

@siren4
Copy link

siren4 commented Aug 15, 2019

相同点:
1.抽象类和接口都不能直接实例化
2.抽象类的子类和接口的实现类都必须实现所有的抽象方法。

不同点:
1.抽象类可以有非抽象的方法,但接口不行(JDK8以后可以有)
2.单继承,多实现
3.接口的成员变量只能是静态常量,没有构造函数,也没有代码块,但抽象类都可以有。
4.抽象类强调的是重用,接口强调的是解耦。

@suagger
Copy link

suagger commented Nov 9, 2019

接口中定义的抽象方法都是public abstract修饰,抽象类的方法可以用public,protected,默认类型
抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
抽象类只能被单继承,但是接口可以被多继承
抽象类中可以有构造器,静态代码块,静态方法,但是接口中不能

@chunlinchulv
Copy link

抽象类中可以有抽象方法和非抽象方法,接口中的所有方法都是抽象的,实现一个接口时,接口中的抽象方法都要被重写

抽象类不能被普通类多继承(Java类只能单继承),但接口可以多实现

抽象类中可以有构造方法、静态代码块和静态方法,接口中没有构造方法、静态代码块和静态方法

抽象类中的变量可以是各种各样的的,接口中不能含有成员变量,除了final和static变量

抽象类和接口都不能被实例化

@syx103
Copy link

syx103 commented Nov 10, 2019

抽象类中有构造法方法,接口中没有构造方法
抽象类中的成员变量可以为任意类型,而接口中的成员变量只能为静态常量
抽象类中可以含有静态方法,接口中没有静态方法
抽象类可以被继承,子类可以不必完全实现其抽象方法,如果子类没有完全实现其抽象方法,子类也为抽象类,子类实现接口必须实现全部的抽象方法
抽象类中的抽象方法可以用public ,protected修饰,但接口中的抽象方法只能用public修饰

@ZHANGfeng-james
Copy link

软件设计角度来看:

  1. 抽象类是自下而上设计的。也就是说先有子类代码的重复,然后再抽象成上层的父类(也就是抽象类);
  2. 接口是自下而上设计的。一般是先考虑设计接口,再去考虑具体的实现。

含义角度来看:

  1. 抽象类表示的是 is a 的关系;
  2. 接口表示的是 has a 的关系;

@FirewingsR
Copy link

相同点
不能直接实例化, 都需要子类实例化

不同点
抽象类可以有方法实现, 接口jdk8后通过 default 可以有方法实现
抽象 is a , 接口 has a
抽象是子类的归纳总结, 接口是公开能力的总结
接口默认/必须是 public 的
接口无构造方法及变量

@971400352
Copy link

大体区别如下:

  • 抽象类可以提供成员方法的实现细节,而接口中只能存在 public 抽象方法;
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的;
  • 接口中不能含有构造器、静态代码块以及静态方法,而抽象类可以有构造器、静态代码块和静态方法;
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口;
  • 抽象类访问速度比接口速度要快,因为接口需要时间去寻找在类中具体实现的方法;
  • 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。如果你往接口中添加方法,那么你必须改变实现该接口的类。

jdk1.8之后接口不是可以写静态方法吗?

@android-zongwei-li
Copy link

我从三个方面来说明它们的区别:
第一点是它们的定义:
1、方法和代码块
在抽象类中可以有构造器、静态方法和非静态方法、以及静态代码块,并且可以提供方法的实现。但是在接口中,jdk1.8以前,只能存在public的抽象方法。jdk1.8以后,可以用default修饰方法,以提供方法的实现。
2、成员变量
抽象类中的成员变量可以是各种类型的,但接口中的成员变量只能是 public static final 类型的。
第二点是它们的使用:
首先,它们都不能被实例化。一个类只能继承一个抽象类,但可以实现多个接口。
第三点是访问速度和拓展性:
抽象类访问速度比接口速度要快,因为接口需要时间去寻找在类中具体实现的方法;
拓展性:要往抽象类中添加新的方法,可以直接提供默认实现,不需要改变现有的代码。往接口中添加方法,还需要改变实现该接口的类。
其他:
抽象类表示的关系是is a;
接口表示的关系是has a。
为什么接口的成员变量用static final修饰:
static:避免子类使用时产生歧义。(子类可能实现多个接口,多个接口的变量名可能一样)
final:既然必须是static修饰的,那么所有子类共享。而接口是一种抽象, 所以一个子类修改了值会影响到其他所有子类,因此就不应该允许子类修改这个值,所以也必须定义为final。

@YuxiangZhu
Copy link

从设计的角度来说,接口是一种规范,用好接口可以很好的进行解耦,自上而下设计可以面向接口编程;而抽象类则是更多的是模板的能力,把子类共有的抽象到父类,可以理解为自下而上的设计;这也是本质区别,相较于使用上和定义上的区别,我认为这个角度来说更有张力

@TheMelody
Copy link

TheMelody commented Apr 12, 2021

接口的设计目的,是对类的行为进行约束(更准确的说是一种“有”约束,因为接口不能规定类不可以有什么行为),
也就是提供一种机制,可以强制要求不同的类具有相同的行为。它只约束了行为的有无,但不对如何实现行为进行限制。
对“接口为何是约束”的理解,我觉得配合泛型食用效果更佳。

而抽象类的设计目的,是代码复用。
当不同的类具有某些相同的行为(记为行为集合A),且其中一部分行为的实现方式一致时(A的非真子集,记为B),
可以让这些类都派生于一个抽象类。在这个抽象类中实现了B,避免让所有的子类来实现B,这就达到了代码复用的目的。
而A减B的部分,留给各个子类自己实现。'正是因为A-B在这里没有实现,所以抽象类不允许实例化出来(否则当调用到A-B时,无法执行)。

🙈🙈🙈🙈
作者:阿法利亚
链接:https://www.zhihu.com/question/20149818/answer/150169365
来源:知乎

@Tang-xun
Copy link

接口 & 抽象类

代码结构:

  1. 接口无构造函数,无成员变量,无静态方法
  2. 抽象类可以有,成员变量,静态类 & 静态方法,并且方法的访问新为做限制,可以有私有实现。

使用方式:
一个类只能继承一个抽象类、但可以实现多个接口

性能:
抽象类的方法访问比接口效率更高,接口的方法调用,需要在实现类找查找具体的实现方法。

解决的问题:
接口:更多是对实现类型为的约束,使 xxx 具有 一组行为 {}
抽象类:更多的是解决类的复用问题,一些减少重复代码

另外解答 ,楼上 @Moosphan SDK设计中接口变更的个人见解

一般,可以定义新接口,实现旧的接口,提供新的接口方法类升级SDK,
这样,可以减少对原有接口的干扰,同时扩展&改变了原有接口能力

参考 Android 嵌套滚动 实现的一组接口:
NestedScrollingChild / NestedScrollingChild2 / NestedScrollingChild3
NestedScrollingParent / NestedScrollingParent2 / NestedScrollingParent3

@freryc
Copy link

freryc commented Mar 3, 2022

相同点:

  1. 都不可以被实例化,只有实现了所有抽象方法的抽象类子类或接口实现类才可以被实例化

不同点:
语法层面上:

  1. 成员变量上:接口只能是public static final的静态常量,而抽象类可以是常量也可以是变量;
  2. 构造器上:接口不能含有构造器、静态代码块和静态方法,而抽象类都可以有;
  3. 方法上:jdk8以前,接口只能有抽象方法,而抽象类可以有默认方法;jdk8以后接口也可以用default声明默认方法;
  4. 一个类只能继承一个抽象类,却能实现多个接口;

性能上:

  1. 抽象类访问速度比接口要快,因为接口需要时间去寻找在类中具体实现的方法;

设计层面上:

  1. 抽象类是对是事物的抽象,接口更多的是对行为的抽象;抽象类侧重于代码复用(模板模式),接口侧重于解耦(策略模式)。

@ThirdPrince
Copy link

抽象类是模板,接口是规范。

@luckilyyg
Copy link

luckilyyg commented Aug 19, 2022 via email

@Empty0Qc
Copy link

Empty0Qc commented Aug 19, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests