封装与抽象?

时间:2012-01-22 12:07:08

标签: java oop

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

抽象:

  

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

封装:

  

它基本上是借助于隐藏对象的状态   我们通过私有,公共,受保护等修饰语来揭示状态   公共方法仅在需要时。

我们使用privatepublic这样的修饰符实现的目标也隐藏了来自外部世界的不必要的细节,这只是一个抽象概念

因此,从上面的解释看,封装是抽象的一部分,或者我们可以说它是抽象的一个子集。但是,为什么封装术语是在我们只能用抽象来处理的时候发明的呢?我确信应该有一些区别于它们的主要区别,但网上的大多数材料对两者都说几乎相同。

虽然这个问题早在这个论坛上已经提出过,但是我再次发布它有特别的疑问。一些回复还说抽象是一个概念,封装是实现。但我不买这个 - 如果这是真的,那么我可以认为提供这两个不同的概念来混淆我们。

更新: - 5年后,我提出了自己的答案,这是基于这篇文章及以下答案的要点

  1. difference between abstraction and encapsulation?
  2. encapsulation vs abstraction real world example

13 个答案:

答案 0 :(得分:115)

抽象是用简单的术语描述某些东西的概念,即抽象出细节,以便专注于重要的东西(这也可以在抽象艺术中看到,例如,艺术家重点关注图像的构建块,例如颜色或形状。同样的想法通过使用继承层次结构转换为OOP,其中更抽象的概念位于顶层,更底层的更具体的概念建立在它们的抽象之上。在最抽象的层面上,根本没有实现细节,也许很少有共同点,随着抽象的减少而增加。

作为一个例子,在顶部可能是一个具有单个方法的接口,然后是下一个级别,提供了几个抽象类,可能会也可能不会填充有关顶级的一些细节,但是通过添加它们的分支自己的抽象方法,然后对于这些抽象类中的每一个都是提供所有其余方法的实现的具体类。

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

答案 1 :(得分:96)

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

抽象是一个更通用的术语,它也可以通过(其中包括)子类来实现。例如,标准库中的接口List是一系列项的抽象,按其位置索引,List的具体示例是ArrayList或{{1} }。与LinkedList摘要交互的代码,用于详细说明正在使用的列表类型。

如果没有通过封装隐藏底层状态,通常不可能进行抽象 - 如果一个类暴露其内部状态,它就不能改变其内部工作,因此不能被抽象。

答案 2 :(得分:28)

  

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

它们是不同的概念。

  • 抽象是精炼所有人的过程 对象的不需要/不重要的属性,只保留 最适合您的域名的特征。

    E.g。对于一个人:你决定保留名字和SSN。 年龄,身高,体重等被忽略为无关紧要。

    抽象是你的设计开始的地方。

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

答案 3 :(得分:24)

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

抽象显示对象的 必要功能

封装用于从外部类和接口隐藏其成员。使用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();

    }

答案 4 :(得分:14)

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

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

您的操作系统的API是底层计算机的抽象。您的编译器提供了一个抽象层,使您免受汇编语言的细节。操作系统内置的TCP / IP堆栈抽象了网络上传输比特的细节。如果你一直走到原始硅片,设计CPU的人就是用“二极管”和“晶体管”编写的电路图,这是电子如何穿过半导体晶体的抽象。

在软件中,一切都是一种抽象。我们构建了模拟或模拟现实某些方面的程序,但必要时我们的模型总是抽象出“真实的东西”的一些细节。我们在抽象层上构建图层,因为这是我们完成任务的唯一方法。 (想象一下,你试图制作一个数独求解器,而你必须只使用半导体晶体来设计它。“好吧,我需要一块N型硅......”)

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

答案 5 :(得分:13)

5年后回答我自己的问题,因为我觉得还需要更多细节

<强>抽象:

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

实际上意味着什么: - 当我说我的公司需要一些媒体/设备以便员工可以连接到客户时。这是最纯粹的抽象形式(如界面) 在java)因为该设备/媒体可以是电话或互联网或skype或亲自或电子邮件等我不会进入设备/媒体的细节

即使我说我的公司需要一些媒体/设备,以便员工可以通过语音通话连接到客户。然后我也在谈论抽象,但在较低的水平,因为设备/媒体可以是电话或Skype或其他等等

现在,当我说我的公司需要一些电话,以便员工可以通过语音电话联系客户。然后我也在谈论抽象,但在电话可以是更低的水平 任何公司,如iPhone或三星或诺基亚等

<强>封装: - 它基本上是在私有,公共,受保护等修饰符的帮助下隐藏对象的状态(信息)。我们只在需要时通过公共方法公开状态。

实际意义: 现在,当我说我的公司需要一些iphone,以便员工可以通过语音通话连接到客户。现在我在谈论一些具体的对象(如iphone)。即使 我也不会在这里讨论iphone的细节,但iphone有一些与设备/媒体没有相关的状态/混凝土信息/实现。当我说 具体对象,实际上它意味着任何具有一些(不完全像java抽象类)实现/信息的对象。

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

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

  1. difference between abstraction and encapsulation?
  2. encapsulation vs abstraction real world example

答案 6 :(得分:5)

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

抽象 - 编写OOP程序时必须遵循一个原则,即说明&#34;您必须在课程中只包含对程序任务感兴趣的组件&#34;。例如:对象学生有很多角色作为人:名字,年龄,体重,头发颜色,眼睛颜色等。但是,当你在OOP中创建一个与学生一起工作的课程时,你应该只包括那些真正的角色学生数据库的事项:姓名,年龄,专业,水平,分数......等 在C ++中,您可以使用修饰符&#34; virtual&#34;来创建抽象类。使用类中的任何方法并使其无法直接使用,但您可以从中派生其他类,并根据任务添加所需成员为其成员创建实现。

答案 7 :(得分:4)

这就是我理解的方式:

在面向对象编程中,我们有一些叫做 classes 的东西。它们适用于什么?它们用于存储某些状态并存储一些方法来更改该状态,即它们是 封装 状态及其方法。

它(类)不关心它自己或其内容的可见性。如果我们选择隐藏状态或某些方法,则 信息隐藏

现在,采用继承的方案。我们有一个基类和一些派生(继承)类。那么,基类在这做什么? 从派生类中抽象出一些东西。

所有这些都不同,对吗?但是,我们将它们混合起来编写好的面向对象程序。希望它有所帮助:)

答案 8 :(得分:3)

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

封装限制外部访问某些部分并捆绑该事物的状态与使用该状态的程序。

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

答案 9 :(得分:1)

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

<强>答案:

当一个类被概念化时,在给定上下文的情况下,我们可以拥有哪些属性。如果我们在动物园的背景下设计动物类,重要的是我们有一个属性作为animalType来描述国内或野生动物。当我们在不同的上下文中设计类时,此属性可能没有意义。

同样,我们在课堂上会有什么样的行为?抽象也在这里应用。有什么是必要的,这将是什么过量?然后我们从班级中删除了一些信息。这个过程正在应用抽象。

当我们要求封装和抽象之间存在差异时,我会说,encapsulation使用抽象作为概念。那么,它只是封装。不,抽象甚至是作为继承和多态性的一部分应用的概念。

Go这里有关于此主题的更多解释。

答案 10 :(得分:1)

让我们尝试以不同的方式理解。

如果没有抽象可能会发生什么,如果没有封装会发生什么。

如果不存在抽象,则可以说对象使用较少。您无法识别对象,也无法访问它的任何功能。举一个电视的例子,如果你没有选择开机,改变频道,增加或减少音量等,那么电视的使用是什么以及你如何使用它?

如果封装不存在或没有正确实现,那么您可能会滥用该对象。数据/组件可能会被误用。以电视的相同例子为例,如果没有对电视音量进行封装,那么音量控制器可能会被低于或超出其限制(0-40 / 50)而被误用。

答案 11 :(得分:1)

Encapsulation保护以从外部实体中折叠对象/实例的内部行为。因此,应提供一个控件来确认所提供的数据不会损害实例/对象的内部系统以使其存在。

很好的例子,Divider是一个具有两个实例变量dividend和divisor以及一个方法getDividedValue的类。

请你想一想,如果除数设置为0,那么内部系统/行为(getDivided)将会中断。

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

答案 12 :(得分:0)

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