封装和抽象是面向对象编程中的两个重要概念。封装是指将数据和相关的操作封装在一个单独的单元中,以便隐藏实现细节并提供对外部的安全访问。它通过将数据和方法组合在一起,形成一个类或对象,从而实现了数据的封装和保护。封装使得代码更加模块化和可维护,同时也提高了代码的安全性和可重用性。 抽象是指将复杂的现实世界问题简化为更易理解和处理的模型。它通过定义抽象类或接口来描述对象的共同特征和行为,而不关注具体的实现细节。抽象使得程序设计更加灵活和可扩展,同时也提高了代码的可读性和可维护性。 封装和抽象是面向对象编程的两个基本原则,它们在设计和实现软件系统时起到了重要的作用。封装强调隐藏实现细节和提供安全访问,而抽象强调简化问题和提供灵活性。通过合理运用封装和抽象,我们可以设计出更加健壮、可扩展和易于维护的软件系统。

144
我今天参加了一次面试。我被问到一个关于面向对象编程(OOP)的问题,即封装(Encapsulation)和抽象(Abstraction)的区别是什么?
我回答道,封装基本上是将数据成员和成员函数绑定到一个称为类的单元中。而抽象基本上是隐藏实现复杂性并为用户提供方便访问。我以为她会对我的回答满意。但她质疑说,如果两者的目的都是隐藏信息,那么这两者之间的实际区别是什么?我无法给她任何答案。
在提出这个问题之前,我阅读了StackOverFlow上关于这两个OOP概念的其他帖子。但我发现自己无法说服面试官。
请问有人能用最简单的例子来解释一下吗?

5
我不知道为什么人们要比较抽象和封装。为什么我们不能将它们作为两个不同的面向对象编程概念来接受呢? - Mr ASquare
6
可能是[抽象和封装的区别?](https://dev59.com/l3RB5IYBdhLWcg3wCjcV)的重复问题。 - logdev
@WpfBee 抽象化与隐藏无关,只需查看我的答案即可。 - S Vinesh
23个回答

135
Encapsulation(封装)是将变量或某些经常更改的实现隐藏在类中,以防止外部直接访问它。他们必须通过getter和setter方法访问它。
抽象化(Abstraction)也用于隐藏一些东西,但在更高的程度上(类,接口)。使用抽象类(或接口)的客户端不关心它是什么,他们只需要知道它能做什么。

14
完美。在我看来,你的回答正是针对我的面试官提出的问题。我正在尝试用一个实际的例子来重申你的回答。请告诉我,如果这符合你的回答。让我们以电视为例。封装是内部电路、LED等组合成电视的部分。抽象化是提供开关、声音、频道设置和其他按钮来操作它。 - WpfBee
1
@Mortalus - 我不同意你的第一句话“抽象与隐藏实现无关”。我认为,当我们开始学习抽象概念时,我们首先被教授的是隐藏实现的复杂性并提供一些接口给用户使用。因为用户可能对实现复杂性不感兴趣。你可以拿电视或空调作为一个实际的例子。另一件事是,如果它不隐藏实现,那么为什么我们在抽象类中提供一个没有主体的方法。我们在这里明显地隐藏了实现。 - WpfBee
1
@Mortalus - 此外,您提到了一个维基链接。它的第一个语句 - “在计算机科学中,抽象是用与其意义(语义)相似的表示来定义数据和程序的过程,同时隐藏实现细节。抽象试图减少和因子化详细信息,以便程序员可以逐个关注一些概念。”本身暗示了抽象旨在隐藏实现细节。我同意您的第二个陈述,但不同意第一个。 - WpfBee
抱歉如果听起来很蠢。我不理解“抽象可以使用接口或抽象类实现”这一行。难道不能使用具体类来实现它,因为它也可以使用适当的访问修饰符隐藏实现细节并显示必要的内容吗? - Imad
2
我认为封装更多地是关于构建一个单一的单元,而不是你是否隐藏它。而抽象更多地是关于隐藏事物,如果我错了,请纠正我。 - raj240
显示剩余3条评论

38

这张图片很好地概括了两者之间的区别:

输入图像描述

来源在这里


28

封装:将代码和数据封装在一个单元中。 是封装的一个例子,因为它包含了方法和属性。

抽象:隐藏内部细节,只显示功能。抽象关注对象做什么而不是如何做到。它提供了类的概括视图。

int number = 5;
string aStringNumber = number.ToString(); 

在这里,ToString()是抽象的。而number变量如何转换为字符串并初始化为aStringNumber是封装的。

让我们以计算器为例。封装是内部电路、电池等组合起来使其成为计算器的部分。抽象是不同的按钮,如开关、清除和其他提供操作它的按钮。


15

抽象化 - 是识别一组对象的共同基本特征的过程(及其结果)。可以说,抽象化是概括的过程:所有被考虑的对象都包含在对象的超集中,所有这些对象都具有给定属性(但在其他方面不同)。

封装 - 是将操作这些数据的数据和函数封装到单个单元中的过程,以便从外部世界隐藏内部实现。

这是一个一般性的答案,与具体的编程语言无关(正如问题所问)。 所以答案是:抽象化和封装没有共同点。 但是它们的实现可能会相互关联(例如,在Java中:封装 - 细节隐藏在类中,抽象化 - 在类或接口中根本没有细节)。


11

是的!!!! 如果我说封装是一种高级的具体范围抽象,有多少人会读/点赞我的答案。 让我们深入探讨为什么我这么说。

在说明之前,我需要澄清两件事情。

一个是数据隐藏, 另一个是抽象

数据隐藏

大多数情况下,我们不会直接访问我们的内部数据。我们的内部数据不应直接外露,因为需要保护特定对象的内部状态,这都涉及到安全性。


抽象

为简单起见,隐藏内部实现被称为抽象。在抽象中,我们只关注必要的事情。“怎么做”而不是“如何做”基本上我们在抽象中谈论的是“要做什么”,因为我们并不会强调“我们如何实现” 在抽象中也可以通过安全性来实现,因为我们不会强调“我们如何实现”。可维护性将得到提高,因为我们可以更改实现,但不会影响最终用户。


我说过,“封装是一种高级的具体范围抽象”。 为什么?因为我们可以看到封装是数据隐藏+抽象

封装 = 数据隐藏 + 抽象

在封装中,我们需要隐藏数据,以便外部人员无法查看数据,并且我们需要提供可用于访问数据的方法。这些方法可能具有验证或其他功能,这些内容也对外部人员隐藏。因此,在这里,我们隐藏了访问方法的实现,这称为抽象。

这就是为什么我会如上所述地说封装是一种抽象的原因。

那么区别在哪里

区别在于,如果我们是为了简单性、可维护性和安全性而向用户隐藏某些东西,则抽象是一般性的,而封装是特定的,与内部状态安全相关,我们在其中隐藏了内部状态(数据隐蔽),并提供了访问数据的方法,同时这些方法的实现也对外部人员隐藏(抽象)。

为什么我们需要抽象

当你进行设计时,你不会谈论实现细节。你会说,如果您将这些参数传递给此方法,它将产生这些输出。我们隐藏了该方法的内部实现,并谈论它将做什么,因此这是一种抽象。

例如

public int add(int a, int b);

这个方法定义告诉我们,如果你提供两个变量,它将执行加法并返回结果。

在这里,我们不会看实现细节,只了解这个方法做什么,而不是如何做。 方法的实现可能因开发人员而异。 1。

public int add(int a, int b){
   return a + b; 
}
public int add(int a, int b){

   return b + a; 
}

两种方法都可以完成相同的任务,但它们的实现方式不同。

基本上,

抽象化需要用来建模系统。封装化需要用来增强系统的安全性。


2
这可能是一个很好的解释,但我觉得它仍然没有回答问题。实际上的问题是,如果两者都涉及隐藏数据(并且一个是另一个的专业化,正如您所说),那么为什么它们在OOPS中是分离的概念?如果一个人既是百万富翁又是亿万富翁,那么我们通常会省略百万富翁部分。明白了吗?(教科书将抽象、封装、继承和多态性列为OOPs的4个概念) - Midhunraj R Pillai
@MidhunrajRPillai,我更新了答案,并说明了抽象化的使用位置。 - Sivaram Rasathurai
@RCvaram,我喜欢您回答中的最后一行。 - A.Soliman

8

这里有一篇很好的文章深入讨论了抽象、封装和信息隐藏之间的区别:http://www.tonymarston.co.uk/php-mysql/abstraction.txt

以下是文章的结论:

抽象、信息隐藏和封装是非常不同但高度相关的概念。可以说,抽象是一种帮助我们确定哪些具体信息应该可见,哪些信息应该隐藏的技术。封装则是将信息打包的技术,以便隐藏应该隐藏的内容,并使意图显示的内容可见。


8

抽象: 通常用来为一组类提供多态访问。 抽象类不能被实例化,因此另一个类将从它派生以创建更具体的表示。

抽象类的常见使用示例可以是模板方法设计模式的实现,其中引入了一个抽象的注入点,以便具体类可以以自己的“具体”方式实现它。

参见:http://en.wikipedia.org/wiki/Abstraction_(computer_science)

封装: 它是隐藏特定类的实现复杂性,使客户端无法访问该复杂性的过程,需要注意的是,“客户端”可能是程序或甚至编写该类的人。

参见:http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)


1
抽象化与抽象类有关吗? - vishnu viswanath
@vishnuviswanath,是的,我们可以使用抽象类和接口来实现抽象化。 - invzbl3

5
一个非常实际的例子是:
假设我想加密我的密码,我只需要调用`encryptionImpl.encrypt(password)`,它会返回一个加密后的密码。
``` public interface Encryption{ public String encrypt(String password); } ```
这被称为抽象,它仅展示应该完成什么任务。
现在让我们假设我们有两种类型的加密方式:MD5和RSA,它们从第三方加密jar中实现了Encryption接口。这些加密类有自己的实现方式,保护了它们的实现不受外部干扰。
这被称为封装,隐藏了实现方式。
记住:应该完成什么任务与如何完成任务是不同的。 隐藏复杂性与保护实现方式。

很好的解释,附带示例。 - saivishnu tammineni

4

没错,抽象和封装确实都与隐藏有关。

  • 设计层面上,只使用相关细节并隐藏不必要的数据被称为抽象。 (例如为一个类“汽车”选择仅相关的属性以使其更抽象或通用。)

  • 封装是在实现层面上隐藏数据的过程。就像如何实际地防止数据被直接/外部访问。这是通过将数据和方法绑定到单个实体/单元来完成的,以防止外部访问。因此,封装也被称为实现层面的数据隐藏。


4
你能解释一下这个答案与其他12个现有答案的区别吗? - Stephen Rauch

4

封装:

类似于药丸一样隐藏某些东西。我们不知道胶囊里面是什么,我们只是吃了它。在编程中也是一样的,我们只是隐藏了某些特殊的方法或属性代码,并且它只会输出结果,就像胶囊一样。简而言之,封装隐藏了数据。

抽象:

抽象意味着隐藏逻辑或实现细节。例如,我们服用药片时,看到它们的颜色,但不知道它的目的和它如何与身体一起工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接