抽象和封装之间的区别?


Answers:


263

这里的大多数答案都集中在OOP上,但是封装要早得多:

  • 每个函数都是一个封装 ; 用伪代码:

    point x = { 1, 4 }
    point y = { 23, 42 }
    
    numeric d = distance(x, y)
    

    在这里,distance封装了平面中两点之间(欧几里得)距离的计算:它隐藏了实现细节。这是封装,纯净而简单。

  • 抽象泛化的过程:采用具体的实现并将其应用于不同的(尽管有些相关)数据类型。抽象的经典示例是C的qsort数据排序功能:

    关于的事情qsort是,它不关心排序的数据-实际上,它不知道排序的数据。而是,它的输入类型是无类型指针(void*),它只是C所说的“我不在乎数据类型”(也称为类型擦除)。重要的一点是qsort,无论数据类型如何,始终保持不变的实现。那唯一改变的是比较功能,它不同于数据类型的数据类型。qsort因此,期望用户将所述比较功能作为函数参数提供。

封装和抽象密切相关,因此您可以指出它们是真正不可分割的。出于实际目的,这可能是正确的。就是说,这不是抽象的封装:

class point {
    numeric x
    numeric y
}

我们封装了点的坐标,但是除了逻辑上将它们分组之外,我们没有实质性地将它们抽象掉。

这是一个非封装的抽象示例:

T pi<T> = 3.1415926535

这是一个具有给定值(π)的通用变量 pi,声明并不关心变量的确切类型。诚然,在实际代码中很难找到这样的东西:抽象实际上总是使用封装。但是,以上内容确实在C ++(14)中通过变量模板存在(=变量的通用模板);语法稍微复杂一些,例如:

template <typename T> constexpr T pi = T{3.1415926535};

26
尽管每种方法都是封装,但它也是一种抽象,因为每次将一些东西放在一起并为其命名时,都会创建一个新的(抽象的)概念。没有抽象的封装是没有用的。因此,他们之间没有共同点是不正确的。
proskor 2014年

@proskor我坚持认为,即使概念的域重叠,它们也是正交的。甚至可以说每个封装都是一个抽象(尽管我不相信),但即使那样,我仍然认为这只是偶然的,而不是任何一个概念的固有属性。
康拉德·鲁道夫

8
它们是不同的,但不是正交的。实际上,我确实认为封装确实是一种特殊的抽象,即结构化的抽象。通过整体上考虑某种复合,我们基本上会忽略(抽象)如何构建其他复合物的细节,即忽略其内部结构。
proskor 2014年

抽象是当我们向用户隐藏实现级别的详细信息,并仅允许访问诸如Sum(1,10)之类的必要值时才对其进行汇总。我们不知道如何。我们已经从用户那里抽象了求和过程。封装的标准定义建议我们何时封装(即制作一个数据和对其执行操作的方法)。有点像上课。将它们绑定到单个实体中。我要介绍的重点是没有什么是强硬路线,两者都需要彼此存在。没有一个,就没有其他。
Saras Arya

2
@psylogic我猜想跳过了“为什么”,因为它看起来太琐碎了:没有抽象和封装,我们就无法编写复杂的系统。即使是中等复杂的问题,也需要如此复杂的程序代码,以至于从一开始它们就会失败。没有抽象,您甚至无法编写程序来打印数字:“打印”概念涉及无数抽象(屏幕是什么?字符是什么?像素是什么?……)
Konrad Rudolph

130

封装隐藏了可能针对通用或特殊行为的实施细节,也可能不是。

抽象是提供一个概括(比如,在一组行为)。

这是一本好书:对象机构的Edward V. Berard的抽象,封装和信息隐藏


6
Neha的链接现在也断开了,但是。我们总是可以用Google搜索商品名称。这是我偶然发现的那个tonymarston.co.uk/php-mysql/abstraction.txt
Abhijeet Apsunde

1
这句话使我明白了:“通常,抽象不是根据信息隐藏来定义的,例如,请注意使用诸如“忽略”和“提取”之类的词。但是,我们也应注意对词语的使用。在上面的一些示例中,“抑制”和“抑制”。简而言之,您可能会说抽象指示某些信息比其他信息更重要,但是(正确地)没有指定处理不重要信息的特定机制。”
Chiel 10 Brinke

1
OOP中的封装并不是要隐藏某些东西。它是关于将状态和行为结合在一起以保护不变量。
尤金·克多伊

121

许多答案及其示例令人误解。

封装就是数据的打包对该数据进行操作的功能到单个组件中,并限制对某些对象组件的访问。
封装意味着对象的内部表示通常在对象定义之外的视图中不可见。

抽象是一种表示基本特征而又不包括实现细节的机制。

封装: - 信息隐藏
抽象: - 实现隐藏

例:

class foo{
    private:
        int a, b;
    public:
        foo(int x=0, int y=0): a(x), b(y) {}

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

foo类的任何对象的内部表示形式都隐藏在类外部。->封装。
对象的任何可访问成员(数据/功能)foo均受限制,并且只能由该对象访问。

foo foo_obj(3, 4);
int sum = foo_obj.add();

方法的实现add是隐藏的。->抽象。


您能否更新您的答案并显示一个反对/不是抽象的封装示例和一个反对/不是封装的抽象示例。
2016年

1
@bjan; qsort在C中使用函数是抽象的示例。您不知道其实现的详细信息。这里不涉及封装。使用构造函数初始化C ++中对象的数据字段是封装的一个示例(通过构造函数控制对对象组件的访问)。
2013年

“抽象:-实现隐藏。” 隐藏从什么实现?
阿伦·拉杰

@ArunRaaj; 来自正在使用它的其他对象。
haccks

3
这应该是最好的答案。简单,清晰,并附带简单示例。
Don Dilanga

99

封装将一些东西放在盒子里,给你一个窥视孔;这可以防止您弄脏齿轮。

完全抽象化忽略了无关紧要的细节,例如物体是否具有齿轮,棘轮,飞轮或核芯。他们只是“走”

封装示例:

  • 内裤
  • 工具箱
  • 钱包
  • 手提包
  • 胶囊
  • 冷冻碳酸​​盐
  • 一个有或没有按钮的盒子
  • 墨西哥卷饼(从技术上讲,墨西哥卷饼周围的玉米饼)

抽象的例子:

  • “事物组”是一种抽象(我们称为聚合)
  • “包含其他事物的事物”是一种抽象(我们称为合成)
  • “容器”是另一种“包含其他事物的事物”的抽象;请注意,所有封装示例都是各种容器,但并非所有容器都具有/提供封装。例如,篮子是不封装其内容物的容器。

12
为什么这被否决?这是在错误答案泛滥的大海中唯一正确的描述之一。
康拉德·鲁道夫

3
在仅提供窥视孔的封装中,我们是否忽略了对用户无关紧要的细节,这就是抽象的含义(如您所说)。这两件事有何不同?也许您可以详细说明。
Sanjeev Kumar Dangi 2010年

63
@Sanjeev封装是具体的,抽象是...抽象的!;-)封装是可以使用的对象,抽象是只能讨论的理想对象。封装是您穿内衣的原因,抽象是您解释内衣和泳衣之间差异的原因
Steven A. Lowe 2010年

6
@psylogic抽象是我们作为思考者处理复杂性的方式:我们忽略无关紧要的细节,强调相关的通用模式,使用符号代替真实对象,并通过它们的行为(在其他抽象模式中)来表征相似的事物。抽象不是计算机科学发明的,它是古老的-象形文字是抽象,单词是抽象,思想是抽象。封装同样古老(内衣,盔甲,盒子)。您可能正在尝试使这些概念变得比实际困难得多。
史蒂文·劳

1
@bjan:我不是说他们不是容器;他们是。我添加了一些不太明显的容器,但封装概念中隐含了“包含”。“容器”是一个抽象。篮子是一个容器,但不封装(完全覆盖,隐藏,保护)其内容物。有帮助吗?
史蒂文·A·劳

64

封装意味着隐藏数据,例如使用getter和setter等。

抽象意味着-使用抽象类和接口等隐藏实现。


您的答案与“抽象是泛化的过程”如何相关-我们如何在抽象类和接口的帮助下实现泛化。你有什么例子吗?
N Sharma

43

抽象是广义术语。即封装是抽象的子集。

在此处输入图片说明

  • 例2:
    解决方案架构师是谁创造了高层次的人抽象的整个解决方案的技术设计,然后这个设计被移交给了开发团队执行

    在这里,解决方案架构师充当抽象,而开发团队充当封装。

  • 示例3:用户数据的封装(网络)

在此处输入图片说明

礼貌

抽象(或模块化)–类型使程序员可以在比位或字节更高的层次上进行思考,而不必为低级的实现所困扰。例如,程序员可以开始将字符串视为一组字符值,而不仅仅是字节数组。更重要的是,类型使程序员能够考虑并表达两个任意大小的子系统之间的接口。这样可以实现更高级别的本地化,以便当这两个子系统进行通信时,子系统互操作性所需的定义保持一致。 资源


这是所有其他答案的“最简单”解释,也应该被接受。
vikramvi

31

上面提供了很多很好的答案,但是我将在这里介绍我的(Java)观点。

数据封装只是意味着包装和控制对一个类中的逻辑分组数据的访问。它通常与另一个关键字“ 数据隐藏”关联。这是使用访问修饰符在Java中实现的

一个简单的例子是定义一个私有变量,并使用getter和setter方法授予对它的访问权,或者使方法成为私有方法,因为它仅与类一起使用。用户无需了解这些方法和变量。

注意:封装完全是关于数据隐藏的,这一点不要误解。当我们说封装时,重点应该放在将相关数据和行为分组或打包或捆绑在一起。

另一方面,数据抽象是泛化的概念,因此底层的复杂逻辑不会暴露给用户。在Java中,这是通过使用接口抽象类来实现的。

范例-

可以说我们有一个Animal接口,它具有一个makeSound()函数。有两个实现此接口的具体类DogCat。这些具体的类具有makeSound()函数的单独实现。现在假设我们有一只动物(我们是从某个外部模块获得的)。所有用户都知道它所接收的对象是一些动物,而打印动物声音是用户的责任。一种蛮力方式是检查接收到的对象以识别其类型,然后其类型转换为该Animal类型,然后在其上调用 makeSound()。但是更巧妙的方法是引用多态事物抽象出来。使用动物作为然后调用makeSound()。在运行时 根据实际对象类型是什么,将调用适当的函数。

更多细节在这里

在此处输入图片说明

复杂的逻辑位于封装在触摸板上的电路板上,并提供了一个不错的界面(按钮)以将其抽象出给用户。

PS:以上链接是我的个人博客。


2
您的博客太好了!现在,我所有的哎呀概念在应用程序中都变得十分清晰!
minigeek

2
到目前为止最好的答案。谢谢。
马里奥·莱维斯克

29
  • 抽象使您可以专注于对象的功能,而不是对象的工作方式
  • 封装意味着隐藏对象的内部细节或机制。

就像您开车时一样,您知道油门踏板的作用,但由于其被封装,您可能不知道其背后的过程。

让我以C#为例。假设您有一个整数:

int Number = 5;
string aStrNumber = Number.ToString();

您可以使用Number.ToString()之类的方法,该方法返回数字5的字符表示形式并将其存储在字符串对象中。该方法告诉您它是做什么的,而不是如何做到的。


我几乎赞成这个简短而准确的答案,但是后来我又看到了汽车的比喻,这使我感到呕吐-哦,我是个好人:P +1
cwap

抱歉,哥们,我添加了一个更好的解释。
jasonco

那么,C语言中的函数也可以抽象吗?
Reddy 2010年

无论使用哪种语言或范式,都可以构建抽象。简短的回答是,C中可以有抽象。为什么不呢?
jasonco's

17
您对抽象和封装的定义是相同的。这就是我的理解-如何完成的工作是隐藏的,而完成的工作则是公开的。在car和Number.ToString()的示例中,您能否精确指出什么是抽象和封装?这将有助于清除问题。
Sanjeev Kumar Dangi 2010年

28

这些概念有些模糊,并非计算机科学和编程所独有。我想提出一些其他想法,以帮助其他人理解这些重要概念。


简短答案

封装 -隐藏和/或限制对系统某些部分的访问,同时公开必要的接口。

抽象化 -除了具体的现实,特定的对象或实际的实例以外,还考虑了某些特征被删除的事物,从而降低了复杂性。

主要相似之处在于这些技术旨在提高理解力和实用性。

主要区别在于抽象是一种更简单地表示事物的方法(通常是使表示更广泛地适用),而封装是一种更改其他事物与事物交互的方式的方法。


长答案

封装形式

这是一个封装示例,希望可以使事情变得更清楚:

Arduino封装

这里我们有一个Arduino Uno和一个位于外壳内的Arduino Uno。外壳很好地说明了封装的意义。

封装旨在保护某些组件免受外界影响和知识,并暴露其他事物应该与之交互的组件。用编程术语来说,这涉及通过访问修饰符隐藏信息,这些修饰符改变了某些变量和/或属性可以读写的程度。

但是除此之外,封装还旨在更有效地提供那些外部接口。在我们的Arduino示例中,其中可能包括漂亮的按钮和屏幕,从而使用户与设备的交互更加简单。它们为用户提供了简单的方法来影响设备的行为并获得有关其操作的有用信息,否则这些信息将更加困难。

在编程中,这涉及到各种部件的分组到一个可分离构建体,例如functionclass,或object。它还包括提供与这些构造进行交互的方式,以及获取有关构造的有用信息的方法。

封装以许多其他方式帮助程序员,其中不仅包括改进的代码可维护性和可测试性。

抽象化

尽管这里有许多其他答案将抽象定义为概括,但我个人认为该定义是错误的。我要说的是,泛化实际上是一种特定抽象类型,而不是相反。换句话说,所有的概括都是抽象的,但并非所有的抽象一定是概括。

这是我喜欢抽象的方式:

像素树

您会说图像中有一棵树吗?您可能会。但这真的是一棵树吗?好吧,当然不会!它是一堆像素,看起来像我们可以称之为树的东西。我们可以说它代表了真实树的抽象。注意,省略了树的一些视觉细节。而且,它不会生长,不会消耗水或产生氧气。怎么可能 它只是屏幕上的一堆颜色,由计算机内存中的字节表示。

这是抽象的本质。这是一种简化事情的方式,使它们更易于理解。贯穿您的每个想法都是现实的抽象。您对树的心理印象不再像此jpeg那样是实际的树。

在编程中,我们可以通过创建一个Tree类来模拟生长,耗水和产生氧气的方法来利用我们的优势。我们的创作将代表我们对实际树木的体验,并且只包含我们为特定模拟真正关心的那些元素。我们使用抽象来表示我们对字节和数学的体验。

抽象类

编程中的抽象还使我们能够考虑几种“具体”对象类型(实际存在的类型)之间的共性,并在唯一实体中定义这些共性。例如,我们的Tree类可能继承自abstract class Plant,后者具有一些适用于我们所有类植物类的属性和方法,但会删除每种植物类型特有的属性和方法。这可以大大减少代码重复,并提高可维护性。

an abstract class和Plain 的实际区别class在于,从概念上讲,没有“真正的”实例abstract class。构造Plant对象没有任何意义,因为不够具体。每个“真实” Plant也是的一种更具体的类型Plant

另外,如果我们希望程序更加逼真,则可能需要考虑这样一个事实,即我们的Tree类本身可能过于抽象。在现实中,每Tree一个更具体的类型的Tree,所以我们可以为那些类型,如创建类BirchMaple等它继承了我们,也许现在abstractTree阶级。

虚拟机

另一个很好的抽象示例是Java虚拟机(JVM),它为Java代码提供了运行的虚拟或抽象计算机。它本质上消除了系统的所有平台特定组件,并提供了“计算机”的抽象接口,而无需特别考虑任何系统。

区别

封装与抽象的不同之处在于,封装与事物的“真实”或“准确”无关。它不会删除某些组件以使其更简单或更广泛地适用。相反,它可以隐藏某些组件以实现类似的目的。


22

封装:正在向对象的实际用户隐藏不需要的/意外的/适当的实现细节。例如

List<string> list = new List<string>();
list.Sort(); /* Here, which sorting algorithm is used and hows its 
implemented is not useful to the user who wants to perform sort, that's 
why its hidden from the user of list. */

抽象:是提供概括性的一种方法,因此是处理种类繁多的对象的通用方法。例如

class Aeroplane : IFlyable, IFuelable, IMachine
{ // Aeroplane's Design says:
  // Aeroplane is a flying object
  // Aeroplane can be fueled
  // Aeroplane is a Machine
}
// But the code related to Pilot, or Driver of Aeroplane is not bothered 
// about Machine or Fuel. Hence,
// pilot code:
IFlyable flyingObj = new Aeroplane();
flyingObj.Fly();
// fighter Pilot related code
IFlyable flyingObj2 = new FighterAeroplane();
flyingObj2.Fly();
// UFO related code 
IFlyable ufoObj = new UFO();
ufoObj.Fly();
// **All the 3 Above codes are genaralized using IFlyable,
// Interface Abstraction**
// Fly related code knows how to fly, irrespective of the type of 
// flying object they are.

// Similarly, Fuel related code:
// Fueling an Aeroplane
IFuelable fuelableObj = new Aeroplane();
fuelableObj.FillFuel();
// Fueling a Car
IFuelable fuelableObj2 = new Car(); // class Car : IFuelable { }
fuelableObj2.FillFuel();

// ** Fueling code does not need know what kind of vehicle it is, so far 
// as it can Fill Fuel**

4
实际上,您的封装示例是抽象的示例。
c

13

抽象和封装之间的区别。

抽象与封装之间的区别


谁能确认差异是抽象在设计级别,封装在实现级别?如果是这样,这确实为我清除了一切!
亚当·卡特

12

抽象:以简化/不同的方式呈现事物的想法,它更易于理解和使用,或者与情况更相关。

考虑一个发送电子邮件的类……它使用抽象将自己展示为某种使者男孩,因此您可以调用emailSender.send(mail,收件人)。它的实际作用-选择POP3 / SMTP,呼叫服务器,MIME转换等。您只会看到您的使者男孩。

封装形式:保护和隐藏对象专有的数据和方法的想法。它使更多事情变得独立和万无一失。

以我为例。我封装了世界其他地方的心率。因为我不希望其他任何人更改该变量,也不需要其他任何人对其进行设置才能正常运行。这对我来说至关重要,但是您不需要知道它是什么,无论如何您可能都不在乎。

环顾四周,您会发现几乎触摸到的所​​有东西都是抽象和封装的一个例子。例如,您的电话为您提供了一种能够将您所说的话说给别人听的抽象概念-涵盖了GSM,处理器架构,无线电频率以及您不了解或不关心的数百万种其他内容。它还封装了您的某些数据,例如序列号,ID号,频率等。

这一切使世界成为生活在:D的美好之地


10

抽象:仅显示必要的信息。让我们集中讨论打开计算机的示例。用户不必知道系统仍在加载时发生了什么(该信息对用户是隐藏的)。

让我们再举一个例子,即ATM。客户不需要知道机器如何读取PIN并处理交易,他所需要做的就是输入PIN,提取现金并离开。

封装:用于隐藏分类的敏感数据,因此将其中的一部分私有化。这是通过不允许外部访问来使某些信息对客户保密的方法。


2
我认为“保持信息私密性的方式”是信息隐藏。封装只是包装信息,可以是私有的也可以是公共的。
不是错误

数据隐藏隐藏了对封装的误解。
thesummersign

8

另一个例子:

假设我创建了一个不可变的Rectangle类,如下所示:

class Rectangle {
 public:
  Rectangle(int width, int height) : width_(width), height_(height) {}
  int width() const { return width_; }
  int height() const { return height_; }

 private:
  int width_;
  int height_;
}

现在很明显,我已经封装了宽度和高度(访问受到了某种限制),但是我还没有抽象任何东西(好的,也许我已经忽略了矩形在坐标空间中的位置,但这是一个缺陷)。例)。

好的抽象通常意味着好的封装。

良好的抽象示例是通用数据库连接类。它的公共接口与数据库无关,并且非常简单,但是允许我通过连接执行所需的操作。你看到了吗?那里也有封装,因为类必须在内部具有所有低级句柄和调用。


8

AbstractionEncapsulation使用一个通用的例子

-------------------------------------------------- -------------------------------------------------- --------------------------------

我们都使用计算器来计算复杂的问题!

图片


2
@NehaChoudhary,我想你是想说Your both example tell about just encapsulation, not abstraction;原因抽象无关具有hiding相当Generalizing
拉胡尔

@Rahul现在,我想他们都不解释封装!
Neha Choudhary 2014年

3
@Devrath如果您想使用calulcator来讲抽象,您可能想像这样去做:有一个计算器的抽象概念,它计算得出的概念是广义的,可以用作制作各种计算器的基本概念。例如,BasicCalculator和ScientificCalculator都实现了自己的计算方式,但最终满足了通用计算器的标准。
Neha Choudhary 2014年

迄今为止,错误答案之海中最好的答案
-Aman

7

一种防止特定对象的数据安全地被外部功能有意或无意地滥用的机制称为“ 数据封装”

在不包括背景细节或解释的情况下表示基本特征的行为称为抽象


7

抽象:抽象是指显示What部分功能。

封装:封装是指隐藏How功能的一部分。

让我们举一个非常简单的例子

/// <summary>
/// We have an Employee class having two properties EmployeeName and EmployeeCode
/// </summary>
public class Employee
{
    public string EmplpyeeName { get; set; }
    public string EmployeeCode { get; set; }

    // Add new employee to DB is the main functionality, so are making it public so that we can expose it to external environment
    // This is ABSTRACTION
    public void AddEmployee(Employee obj)
    {
        // "Creation of DB connection" and "To check if employee exists" are internal details which we have hide from external environment
        // You can see that these methods are private, external environment just need "What" part only
        CreateDBConnection();
        CheckIfEmployeeExists();
    }


    // ENCAPLUSATION using private keyword
    private bool CheckIfEmployeeExists()
    {
        // Here we can validate if the employee already exists
        return true;
    }

    // ENCAPLUSATION using private keyword
    private void CreateDBConnection()
    {
        // Create DB connection code
    }
}

控制台应用程序的程序类

class Program
{
    static void Main(string[] args)
    {
        Employee obj = new Employee();
        obj.EmplpyeeName = "001";
        obj.EmployeeCode = "Raj";

        // We have exposed only what part of the functionality
        obj.AddEmployee(obj);
    }
}

6

让我们以堆栈为例。可以使用数组或链接列表来实现。但是它支持的操作是推送和弹出。

现在,抽象仅公开接口push和pop。基础表示是隐藏的(是数组还是链表?),并提供了定义良好的接口。现在,如何确保不会意外访问抽象数据?这就是封装的来源。例如,C ++中的类使用访问说明符,以确保防止意外访问和修改。而且,通过将上述接口公开,可以确保操作堆栈的唯一方法是通过定义明确的接口。在此过程中,它已经将数据和可以操纵它的代码耦合在一起(这里不涉及好友功能)。即,代码和数据被绑定在一起或捆绑或封装。


5

封装将复杂性封装在一个类(因此是封装)中,因此……抽象是对象的特征,与其他对象有所不同...

可以通过使具有一个或多个方法的类抽象化来实现抽象。这不过是扩展类应该实现的特性。例如,当您发明/设计汽车时,您要定义一个特征,例如汽车应具有4个门,门,方向盘等…,因此任何使用此设计的人都应包括该特征。实现不是抽象的头。它将仅定义应包括的特征。

通过使用访问修饰符(如public,private,protected以及继承,聚合或组合),可以将数据和行为保存在class&的一个封装中,从而实现封装。因此,您也只显示所需的内容,只显示想要显示的范围。例如,公共的,受保护的,友好的和私人的ka基础……例如,通用汽车决定使用上面抽象的汽车设计。但是他们拥有具有相同特性和几乎相同功能的各种产品。因此,他们编写了扩展上述抽象类的类。它说齿轮箱应该如何工作,刹车应该如何工作,方向盘应该如何工作。然后所有产品都使用此通用功能。他们不需要知道齿轮箱是如何工作的,折断的工作原理或转向器的工作原理。

两者都很强大;但是使用抽象比封装需要更多的技能,并且更大的应用程序/产品在没有抽象的情况下无法生存。


“使用抽象比封装需要更多的技能”?需要引用。
Johnsyweb

5

抽象-隐藏实现-设计时-使用界面/抽象计算

封装-隐藏数据-在开发中----使用访问修饰符(公共/私有)


4

这个

OOPS中封装与抽象之间的区别

抽象和封装是两个重要的面向对象编程(OOPS)概念。封装和抽象都是相互关联的术语。

封装与抽象之间的现实差异

封装意味着隐藏。封装也称为数据隐藏。您可以认为封装就像将药物隐藏在其中的胶囊(药片)一样。封装是包装,只是隐藏属性和方法。封装用于将代码和数据隐藏在一个单元中,以保护数据免受外界干扰。类是封装的最佳示例。

抽象是指仅向目标用户显示必要的细节。顾名思义,抽象是“任何事物的抽象形式”。我们在编程语言中使用抽象来制作抽象类。抽象类表示类的方法和属性的抽象视图。

封装和抽象之间的实现差异

  1. 使用接口和抽象类实现抽象,而使用私有和受保护的访问修饰符实现封装。

  2. OOPS通过防止程序员以非预期的方式访问数据来利用封装来增强类型的完整性(即,确保以适当的方式使用数据)。通过封装,只有预定的一组功能可以访问数据。与访问限制(公共/私有等)捆绑在一起的数据类型和操作(方法)的总称是一类。


4

我将尝试以一种简单的方式来演示封装。

  • 将数据和功能包装到单个单元(称为类)中的过程称为封装。封装包含和隐藏有关对象的信息,例如内部数据结构和代码。

封装是-

  • 隐藏复杂性
  • 将数据和功能绑定在一起,
  • 将复杂方法设为私有,
  • 将实例变量设为私有,
  • 隐藏来自最终用户的不必要的数据和功能。

封装实现抽象。

而且抽象是-

  • 显示必要的内容
  • 数据需要从最终用户中提取,

让我们看一个例子-

下图显示了“要添加到数据库中的客户详细信息”的GUI。

客户屏幕GUI

通过查看图像,我们可以说我们需要一个客户类别。

步骤-1:我的客户类别需要什么?

  • 2个变量,用于存储客户代码和客户名称。
  • 1将客户代码和客户名称添加到数据库的功能。

    名称空间CustomerContent {公共类Customer {公共字符串CustomerCode =“”; 公用字符串CustomerName =“”; public void ADD(){//我的数据库代码会在这里}

现在,只有ADD方法无法在这里单独使用。

步骤-2:ADD功能的验证如何起作用?

我们将需要数据库连接代码和验证代码(其他方法)。

public bool Validate()
{
    //Granular Customer Code and Name
    return true;
}

public bool CreateDBObject()
{
    //DB Connection Code
    return true;
}


class Program
{
static void main(String[] args)
{
CustomerComponent.Customer obj = new CustomerComponent.Customer;

obj.CustomerCode = "s001";
obj.CustomerName = "Mac";

obj.Validate();
obj.CreateDBObject();

obj.ADD();
}
}

现在无需向最终用户显示Extra方法(Validate(); CreateDBObject()[复杂方法和Extra方法])。最终用户只需查看并了解客户代码,客户名称和添加按钮即可添加最终用户不在乎它将如何将数据添加到数据库?。

步骤-3:私有不涉及最终用户交互的其他复杂方法。

因此,将那些复杂的Extra方法设为Private而不是Public(即,隐藏这些方法)并删除obj.Validate();。obj.CreateDBObject(); 从主类Program中,我们实现了封装。

换句话说,简化与最终用户的接口就是封装。

所以现在代码如下所示-

namespace CustomerContent
{
public class Customer
{
public string CustomerCode = "";
public string CustomerName = "";
public void ADD()
{
   //my DB code will go here
}

private bool Validate()
{
    //Granular Customer Code and Name
    return true;
}

private bool CreateDBObject()
{
    //DB Connection Code
    return true;
}


class Program
{
static void main(String[] args)
{
CustomerComponent.Customer obj = new CustomerComponent.Customer;

obj.CustomerCode = "s001";

obj.CustomerName = "Mac";

obj.ADD();
}
}

总结:

步骤-1:我的客户分类需要什么?是抽象。

步骤-3:步骤-3:将不涉及最终用户交互的额外复杂方法私有化。

PS-上面的代码很难实现。


4

以下段落帮助我了解它们之间的区别:

数据封装是捆绑数据的机制,使用它们的功能和数据抽象是仅公开接口并向用户隐藏实现细节的机制。

您可以在这里阅读更多内容。


3

对于抽象或封装,信息隐藏不是严格要求的。信息可能会被忽略,但不必隐藏。

封装 是将某事物视为一件事物的能力,即使它可能由许多复杂的部分或构想组成。例如,我可以说我坐在“椅子”上,而不是指椅子的许多不同部分,每个部分都有特定的设计和功能,所有这些部分都精确地装配在一起,目的是舒适地握住我的臀部几英尺远离地板。

通过封装启用抽象。因为我们封装了对象,所以我们可以将它们视为以某种方式彼此关联的事物,而不必陷入内部对象结构的微妙细节中。抽象是考虑更大的图景的能力,而不必担心小细节。这个词的根是抽象的,就像出现在学术论文顶部的摘要中一样,而不是抽象的类,而只能是作为派生子类实例化的类。

老实说,当我把屁股放到椅子上时,我从没想过椅子的结构如何抓住并保持体重。这是一个足够体面的椅子,我不必担心这些细节。因此,我可以将注意力转向计算机。再说一次,我不考虑计算机的组成部分。我只是在看网页的一部分,该部分代表我可以输入的文本区域,而且我正在用文字进行交流,甚至根本没有想到我的手指如何总是如此迅速地在键盘上找到正确的字母,以及如何最终在点击这些键和发布到该论坛之间建立了联系。这是抽象的强大力量。由于可以信任较低级别的系统,因此可以一致且精确地工作,因此,我们会留意进行更多工作。


2
class Aeroplane : IFlyable, IFuelable, IMachine
{ // Aeroplane's Design says:
  // Aeroplane is a flying object
  // Aeroplane can be fueled
  // Aeroplane is a Machine
}
// But the code related to Pilot, or Driver of Aeroplane is not bothered 
// about Machine or Fuel. Hence,
// pilot code:
IFlyable flyingObj = new Aeroplane();
flyingObj.Fly();
// fighter Pilot related code
IFlyable flyingObj2 = new FighterAeroplane();
flyingObj2.Fly();
// UFO related code 
IFlyable ufoObj = new UFO();
ufoObj.Fly();
// **All the 3 Above codes are genaralized using IFlyable,
// Interface Abstraction**
// Fly related code knows how to fly, irrespective of the type of 
// flying object they are.

// Similarly, Fuel related code:
// Fueling an Aeroplane
IFuelable fuelableObj = new Aeroplane();
fuelableObj.FillFuel();
// Fueling a Car
IFuelable fuelableObj2 = new Car(); // class Car : IFuelable { }
fuelableObj2.FillFuel();

// ** Fueling code does not need know what kind of vehicle it is, so far 
// as it can Fill Fuel**


2

抽象和封装的过程都生成接口。

通过封装生成的接口隐藏了实现细节。

与抽象之前相比,通过抽象生成的接口可应用于更多数据类型。


2

Abstraction是我们要做的实施合同。实施可能会随着时间的流逝而改变。各种实现本身可能会隐藏,也可能不会隐藏,但会被屏蔽在抽象后面。

假设我们定义所有的APIs一类在interface那么请问我们的代码在用户的定义为depened APIsinterface。仅在必须遵守既定合同的情况下,我们才能自由地改进或修改实施。用户未耦合与我们的实施结合。

我们以抽象方式公开所有必要规则(方法),这些规则的实现留给实现者实体,而实现也不属于抽象的一部分。它只是签名声明,是什么构成了抽象。

Encapsulation只是通过减少状态和行为的访问来隐藏内部细节。封装的类可能没有定义好Abstraction

java.util.List是的抽象java.util.ArrayListjava.util.ArrayListnon public访问修饰符标记的内部状态是封装。

编辑 假设一类Container.nava implements IContainerIContainer可以声明的方法,如addElementremoveElementscontains,等在这里IContainer代表了它的实现类的抽象。抽象是将类,模块或系统的API声明给外部世界。这些API成为contract。该系统可能尚未开发。系统的用户现在可以依赖于声明的API,并确保任何实施此类合同的系统将始终遵守声明的API,他们将始终为这些API提供实现。一旦我们写了一个具体的实体,然后决定隐藏我们的内部状态就是封装



1

简而言之

抽象使用->封装封装使用->数据隐藏

要么

数据隐藏是封装的一个子集,并 封装是抽象的一个子集

参考:http : //www.tonymarston.co.uk/php-mysql/abstraction.txt


封装如何使用数据隐藏?累积 对Tony Marston而言,封装只是包裹实体,而没有提及隐藏行为。如果封装是“与信息隐藏相同”,则可能会提出这样的论点:“封装的所有内容也都被隐藏了”。这显然是不正确的。例如,即使信息可以封装在记录结构和数组中,该信息通常也不会被隐藏(除非通过某种其他机制被隐藏)。
Harshul Sharma
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.