我试图了解这两个元素有何不同。我在这里和这里阅读,以及我正在学习的讲座。如果我理解正确,除了定义和连接之外,我还看到以下可能性:
抽象类
- 不能实例化一个类
- 至少必须定义方法的标头,因此继承者必须覆盖此方法
- 方法可以完全实现
- 该方法可以被继承人覆盖,因此将获得1个方法
- 不固定的变量值
界面
- 接口无法实例化
- 必须定义方法头
- 该方法可以被覆盖,结果将有2个方法(尽管如果一个就足够了,为什么我们需要这么多方法)
- 方法可以使用默认值定义
- 变量的固定值
我知道接口定义状态,而抽象类定义状态和行为。那么为什么不只使用一个变体,例如一个类呢?
我们只能从一个类继承,但可以从多个接口继承。但是,为什么不创建更多的抽象类并相互继承,从而在工作类中继承一些东西呢?
什么时候应该使用一个而不是另一个?
是否存在需要使用一个或另一个选项的用例?
对Java中的应用程序感兴趣。
加法 假设有这样的结构。
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
abstract double area();
}
有一个三角形类:
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b);
}
double area() {
System.out.println("B области четырехугольника.");
return dim1 * dim2;
}
}
有一个正方形类:
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
double area() {
System.out.println("B области треугольника.");
return dim1 * dim2 / 2;
}
}
有一个入口点:
class AbsractAreas {
public static void main(String[] args) {
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figRef = r;
System.out.println("Площадь равна " + figRef.area());
figRef = t;
System.out.println("Площадь равна " + figRef.area());
}
}
我可以将其转换为接口吗?应该转换成接口吗?还是应该一分为二?
PS:接口的附加问题。我知道接口旨在保护类的工作方式。但是对类施加限制还不够吗(我的意思是访问修饰符)?
PS PS:为什么要在接口中添加定义方法体的功能?而现在,如果我在接口中定义一个方法,例如move (int n),在继承人中,我需要使用move (int n, int m). 用一个方法创建一个抽象类move ()然后重新定义它以获得所需数量的参数不是更容易吗?或者您是否有能力在接口中覆盖方法中的参数数量?还是我们仍然有两种方法move (int n)和move (int n, int m)?
PS PS PS:抱歉这么多问题。我只是想深入了解这个问题。)
接口定义了行为,一般意义上,接口告诉了如何与这个接口实现的类一起工作,例如所有的门都可以关闭和打开,不管它是什么门,它是怎样的制造,主要是它是一扇门,它有打开和关闭的方法。接口可以被在任何意义上彼此不相关的类使用(以 Comparable 为例)。最重要的是多重继承。
抽象类定义行为和状态。抽象类用于继承(即我们之间有密切关系的类),用它来描述继承人的共同特征。它可以包含特定的(在接口中也使用 java 8)和静态方法。
PS我发现一篇文章很可能会帮助您更好地理解差异链接
考虑一个需要接口并且不能省略抽象类的示例。
这是我们需要在一个类中组合多个功能方面的情况,而这些方面之间没有任何关系(因此制作抽象类并相互继承是不切实际的,甚至是不可能的)。
让我用一个例子来解释。假设我们需要机会
为此,您可以创建如下接口:
或者 - 创建具有相同方法的抽象类。
您需要了解这些类或接口并不是凭空存在的。我们假设这些接口(或类)具有使用它们的客户端,例如库。例如,
Serilizable- 用于通过网络进行消息传递的库的Comparable一部分,以及 - 用于处理馆藏的库的一部分。那些。某处有使用它们的功能:
现在,当我们想要创建一个应该能够复制自身的具体类,以便它可以进行比较和序列化时,使用接口一切都很简单——我们创建一个类并实现所有三个接口。
如果我们使用抽象类,就会出现问题:
总之,抽象类不适合这项任务。主要原因是java中缺少多重继承。多重继承可以解决这个问题,但代价是引入了新问题(多重继承本身固有的)。
接口(特别是从 java8 开始)可以取代抽象类(与其他措施一起)。但有时使用抽象类可能更实用。
假设我们正在创建一个用于在数据库中保存对象的库。您可以为可以持久化的对象创建一个接口:
但是,在这种情况下,实现的每个具体类
Persistable都必须定义一个字段id。如果有很多这样的类,那么把它变成Persistable一个抽象类然后它可以存储状态可能更实用:这当然是一个简单的例子,在这里是不合理的,但是如果有更多这样的字段,加上这些字段必须满足某些条件,才能
Persistable正确构造对象(例如,什么id != null),那么可以让继承类对此感到不舒服,因为 相同的逻辑将在多个地方,并且在支持方面将其放在一个地方更方便。这可以帮助检测后继者中的错误,其中后继者(非恶意)在早期阶段错误地实现了接口。
当然,实现实现继承和使用抽象类也有缺点,在特定情况下需要考虑和权衡。
在大多数情况下,接口是常见行为的标志。例如,如果您的对象可以被克隆,那么在其类的祖先中可能有一个 interface
Cloneable。如果对象是可移动的,那么 -Moveable等等。并且标志的方法是适当的——它们的目的是指定这个!,而不是实现标志接口继承者的类对象的行为。抽象类仍然是一个类,或“下类”。也就是说,实体与具体类相同,但缺少一些东西。
例如,一个抽象类
Shape (Форма)是一个实体/类,但是我们不能说这个形状到底是什么(立方体,正方形,圆形,平行六面体),例如,我们不能说如何绘制它,或者抓取它,或者改变如何它有很多顶点和边,所以这个实体很可能有某种部分实现,例如,改变和存储窗体中心在空间或平面上的位置的方法,但我们将离开显示和这种实体对后代/继承人的特定行为。如果有架构/语义需要,这两种结构本身可以继承相同的接口和抽象类。
Z.Y. 了解差异的最佳方法是实践!在开发应用架构和后续实现的过程中,相同的实体之一可以先成为接口,然后是类(甚至是抽象类),反之亦然)