封装还是抽象?


137

这是封装和抽象的简要定义。

抽象:

Java中的抽象过程用于隐藏某些细节,仅显示对象的基本功能。换句话说,它处理对象(接口)的外部视图。我在不同站点上看到的唯一好的示例是接口。

封装形式:

它基本上是关于借助诸如private,public,protected等修饰符隐藏对象的状态。我们仅在需要时才通过public方法公开状态。

我们使用修改器实现象privatepublic也从侧面走出世界,不过也有抽象概念隐藏不必要的细节

因此,从上面的解释看来,封装是抽象的一部分,或者我们可以说它是抽象的子集。但是为什么当我们只能用抽象来处理封装术语时呢?我相信应该有一些主要的区别将它们区分开,但是网上的大多数材料对两者都说得差不多。

尽管这个问题早些时候也曾在这个论坛上提出过,但是我再次带着特定的疑问再次发布它。一些答复还说抽象是一个概念,封装是实现。但是我不买这个-如果是真的,那么我可以认为提供了这两个不同的概念来使我们感到困惑。

更新:-五年后,我根据这篇文章及其以下答案给出了自己的答案,这就是要点

  1. 和封装之间的区别?
  2. 封装与抽象的真实世界示例

上面定义的封装是一种抽象的工具,但是我倾向于将其视为类封装的内容(功能/数据,与访问无关),而抽象更像是使您摆脱对具体实现的关注,即无论如何它完成了,并且究竟做了什么,可以从维基百科上进行An 'abstraction' (noun) is a concept that acts as a super-categorical noun for all subordinate concepts, and connects any related concepts as a group, field, or category.
TI

封装更多地是绑定与上下文有关的相关细节(数据和对数据进行操作的行为)。这也可以通过不使用访问说明符(如)来实现private public,因为它们仅提供信息/数据隐藏,而我们这样做是因为保护实例数据是一种好习惯。
user3227986 '16

Answers:


98

封装是一种用作抽象的一部分的策略。封装是指对象的状态-对象将其状态封装起来并从外部隐藏起来;类的外部用户通过其方法与之交互,但无法直接访问类的状态。因此,该类将与状态相关的实现细节抽象出来。

抽象是一个更通用的术语,它也可以通过(以及其他)子类实现。例如,该接口List在标准库是用于项的序列,可以通过位置索引的抽象,的具体实例List是一个ArrayList或一个LinkedList。与List摘要交互的代码,它使用的是哪种列表的详细信息。

如果不通过封装隐藏基础状态,则通常不可能进行抽象-如果类公开其内部状态,则它无法更改其内部工作方式,因此无法抽象。


8
封装意味着将一组相关的属性,方法和其他成员视为单个单元或对象。 msdn.microsoft.com/zh-CN/library/dd460654.aspx
raberana 2015年

1
封装导致抽象。
马丁

124

抽象是用更简单的术语来描述事物的概念,即抽象出细节,以便专注于重要的事物(例如,在抽象艺术中也可以看到,例如,艺术家专注于图像的构成要素,例如颜色或形状)。同一思想通过使用继承层次结构转换为OOP,在继承层次中,更多抽象概念位于顶部,更具体的思想位于底部,基于它们的抽象。在其最抽象的级别上,根本没有实现细节,也许只有很少的共性,这些共性随着抽象的减少而增加。

例如,最上面可能是带有单个方法的接口,然后下一个级别提供了几个抽象类,这些抽象类可能会也可能不会填写有关顶层的某些细节,而是通过添加自己的抽象方法进行分支,那么对于这些​​抽象类中的每一个,都是提供所有其余方法的实现的具体类。

封装是一种技术。它可能是也可能不是用于辅助抽象,但是肯定是关于信息隐藏和/或组织的。它要求以某种方式对数据和功能进行分组-当然,良好的OOP实践要求应将它们按抽象进行分组。但是,还有其他用途仅有助于维护性等。


13
您对抽象的定义是我所见过的最好的,而且我感觉这是有史以来第一次,它在我的脑海中震撼并变得有意义。我知道距您发布此消息已有3年多了,但是谢谢。
Casey Crookston,2015年

1
哇...抽象...用艺术来表达...红色可能是愤怒,这就是我们需要知道的!感谢您对此概念的看法:-)
SlowLearner

封装用于实现“松散耦合和高凝聚力”。
分拣机

28

封装是抽象的一部分,或者我们可以说它是抽象的子集

它们是不同的概念。

  • 抽象是完善对象的所有不需要/不重要属性并仅保留最适合您的域的特征的过程。

    例如,对于一个人:您决定保留名字和姓氏以及SSN。年龄,身高,体重等无关紧要。

    抽象是设计开始的地方。

  • 封装是下一步,它可以识别对您接受的在抽象过程中保留的属性适用的操作。数据与作用于它们的操作的关联。
    即数据和方法捆绑在一起。

我们可以说抽象是一种设计概念,而封装主要涉及我们在抽象期间达成一致的设计的实现?
M Sach 2012年

1
在封装中,您定义了可以/必须应用于数据的操作。这也可以是设计的一部分。例如,检索SSN,但不能对其进行修改
Cratylus 2012年

25

封装 不必要的数据隐藏在胶囊或单元中

抽象显示 对象的基本特征

封装用于从外部类和接口中隐藏其成员。使用c#中提供的访问修饰符,例如public,private,protected等。例如:

Class Learn
{
  private int a;         // by making it private we are hiding it from other
  private void show()   //class to access it
  {
   console.writeline(a);
  }
}

在这里,我们将数据包装在一个单元或胶囊中,即Class。

抽象与封装相反。

抽象用于向用户显示重要和相关的数据。最佳现实示例在移动电话中,您会看到它们的不同类型的功能,例如摄像头,mp3播放器,呼叫功能,录音功能,多媒体等。这是抽象的,因为您仅看到相关信息,而不是其内部工程。

 abstract class MobilePhone
    {
        public void Calling();       //put necessary or essential data
        public void SendSMS();       //calling n sms are main in mobile
    }

    public class BlackBerry : MobilePhone   // inherited main feature
    {
        public void FMRadio();            //added new
        public void MP3();
        public void Camera();
        public void Recording();

    }

我同意。这些家伙有点对立。好的oop倾向于将不变的事物抽象化,并[封装确实变化的事物] [1]。[1]:principles-wiki.net/...
雷Tayek

15

抽象是一个非常笼统的术语,软件中的抽象不限于面向对象的语言。词典定义:“将事物视为一般品质或特征的行为,除了具体的现实,特定的对象或实际实例以外”。

汇编语言可以看作是机器代码的抽象-汇编表达了机器代码的基本细节和结构,但使您不必考虑所使用的操作码,代码在内存中的布局,从而跳转到正确的地址等

操作系统的API是基础计算机的抽象。编译器提供了一层抽象层,使您免受汇编语言细节的影响。操作系统中内置的TCP / IP堆栈抽象了通过网络传输位的细节。如果您一直走到原始硅,设计CPU的人就是使用用“二极管”和“晶体管”编写的电路图来完成的,这些电路图是电子如何通过半导体晶体传播的抽象概念。

在软件中,一切都是抽象。我们构建的程序可以对现实的某些方面进行模拟或建模,但是有必要使我们的模型始终抽象出“真实事物”的某些细节。我们是一层一层接一层的抽象,因为这是完成任何事情的唯一方法。(想象一下,您试图制造一个数独求解器,而您只能使用半导体晶体来设计它。“好吧,我这里需要一块N型硅...”)

相比之下,“封装”是一个非常具体且受限制的术语。这个问题的其他一些答案已经给出了很好的定义。


14

5年后回答我自己的问题,因为我仍然需要更多详细信息

抽象:

技术定义:- 抽象是一种概念,用于隐藏不必要的细节(复杂或简单),仅显示对象的基本特征。这里没有实现,只是一个概念

实际上意味着什么:-当我说我的公司需要某种媒介/设备时,员工才能与客户建立联系。这是摘要的最纯粹形式(例如java中的接口),因为该设备/介质可以是电话,互联网或Skype,也可以是亲自或电子邮件等。

即使我说我的公司需要某种媒介/设备,以便员工可以通过语音呼叫与客户建立联系。然后我也在说抽象,但在较低的级别,因为设备/介质可以是电话或Skype或其他东西等

现在,当我说我的公司需要一些电话时,员工才能通过语音呼叫与客户建立联系。然后我也在说抽象,但水平较低,因为电话可以是任何公司,例如iphone或samsung或nokia等

封装:- 基本上是借助诸如private,public,protected等修饰符来隐藏对象的状态(信息)。只有在需要时,我们才通过public方法公开状态。

实际上是什么意思:- 现在我说我的公司需要一些iphone,以便员工可以通过语音呼叫与客户建立联系。现在,我正在谈论一些具体的对象(例如iphone)。即使我也没有在这里讨论iphone的细节,但iphone具有某些状态/具体信息/实现,而设备/介质则没有。当我说具体对象时,实际上是指任何与之相关联的对象(不像java抽象类一样完整)。

因此,iphone实际上在这里使用封装作为隐藏其状态/信息并仅公开它认为应该公开的策略的策略。因此,抽象和封装都隐藏了一些不必要的细节,但是抽象是在概念级别,而封装实际上是在实现级别

这是基于这篇文章及其以下答案的要点

  1. 和封装之间的区别?
  2. 封装与抽象的真实世界示例

5

封装 -隐藏类组件以防止从外部直接访问的过程。通过使用“私有”修饰符可以防止其他类或对象直接访问某些类成员(数据字段或方法),同时提供公共成员对这些私有成员的访问(接口)来实现。这使得班级成员受到保护,因为人体器官被隐藏/封装在皮肤或某些防护罩下。

抽象 -编写OOP程序必须遵循一个原则,即“您必须在类中仅包含程序任务中感兴趣的组件”。例如:对象学生具有很多人的性格:姓名,年龄,体重,头发的颜色,眼睛的颜色等。但是,当您在OOP中创建一个班级与学生一起工作时,您应该只包括那些真正对于学生数据库的问题:名称,年龄,专业,级别,分数等。在C ++中,您可以通过对类中的任何方法使用修饰符“ virtual”来创建抽象类,这将使其直接无法使用,但是您可以从中派生其他类,并根据任务添加所需的成员为其成员创建实现。


4

这就是我的理解:

在面向对象的编程中,我们有一个叫做类的东西。他们是干什么的?它们将存储一些状态并存储一些更改状态的方法,即它们正在封装状态及其方法。

It(class)不在乎其自身或其内容的可见性。如果我们选择隐藏状态或某些方法,那就是信息隐藏

现在,以继承为例。我们有一个基类和几个派生(继承)的类。那么,基类在这里做什么呢?它从派生类中抽象出一些东西。

他们都是不同的,对吗?但是,我们将它们混合在一起以编写良好的面向对象程序。希望能帮助到你 :)


3

抽象描述了特定于上下文的简化表示;它忽略上下文无关的详细信息,并包括上下文重要的详细信息。

封装限制了外部访问某事物的部分,并将事物状态与使用状态的过程捆绑在一起。


以人为例。在外科手术中,有用的抽象忽略了一个人的宗教信仰,并包括了这个人的身体。此外,人们用使用这些记忆的思维过程来封装他们的记忆。抽象不需要封装。例如,一个人的绘画既不会隐藏其部件,也不会将程序与状态捆绑在一起。并且,封装不需要具有关联的抽象;例如,真实的人(不是抽象的人)通过新陈代谢来封装自己的器官。


1

注意:我正在分享。这并不是说这里不是一个很好的答案,而是因为我很容易理解。

回答:

当一个类被概念化时,给定上下文我们可以在其中拥有什么属性。如果我们要在动物园的环境中设计动物类,那么重要的是,我们必须使用属性animalType来描述家养或野生动物。当我们在不同的上下文中设计类时,此属性可能没有意义。

同样,我们在课堂上会有哪些行为?抽象也适用于此。在这里需要什么?过量是什么?然后,我们从课堂上截取了一些信息。此过程正在应用抽象。

当我们要求封装与抽象之间的区别时,我会说封装是将抽象作为一个概念。因此,这仅仅是封装。不,抽象甚至是作为继承和多态性的一部分应用的概念。

请转到此处以获取有关此主题的更多说明。


1

让我们尝试以另一种方式理解。

如果不存在抽象会发生什么,如果不存在封装会发生什么。

如果不存在抽象,则可以说该对象的使用较少。您无法识别该对象,也无法访问其任何功能。以电视为例,如果您没有开机,更改频道,增大或减小音量等选项,那么电视的用途是什么?如何使用它?

如果封装不存在或未正确实施,则可能会滥用该对象。那里的数据/组件可能会被滥用。以电视的相同示例为例,如果未对电视的音量进行封装,则音量控制器可能会因为低于或超过其限制(0-40 / 50)而被滥用。


1

封装可以防止外部实体破坏对象/实例的内部行为。因此,应提供控制以确认所提供的数据不会损害实例/对象的内部系统以使其生存。

很好的例子,除法器是一个具有两个实例变量的除数和除数的类以及一个方法getDividedValue。

您能否认为,如果将除数设置为0,则内部系统/行为(getDivided)将中断。

因此,可以通过方法抛出异常来保护对象的内部行为。


0

我简单地说:抽象的本质是在提取必要的属性的同时省略不必要的细节。但是,为什么我们要忽略无关紧要的细节呢?关键动机是防止变更的风险。您可能会认为抽象与封装相同。但是封装意味着将一个或多个项目封装在容器中而不隐藏细​​节的行为。如果您提出“封装的所有内容也都被隐藏”的说法。这显然是不正确的。例如,即使信息可以封装在记录结构和数组中,该信息通常也不会被隐藏(除非通过某种其他机制被隐藏)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.