抽象和封装之间的区别?

封装和抽象的精确区别是什么?

这里的大部分答案都集中在OOP上,但封装很早就开始了:

  • 每个function都是封装 ; 伪代码:

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

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

  • 抽象是泛化的过程 :采取一个具体的实现,并使其适用于不同的,虽然有点相关的数据types。 抽象的经典例子是对数据进行sorting的C的qsort函数:

    关于qsort的事情是,它不关心它sorting的数据 – 事实上,它不知道它分类的数据。 相反,它的inputtypes是一个无types的指针( void* ),它只是C说“我不关心数据types”(这也称为types擦除)的方式。 重要的一点是qsort的实现总是保持不变,不pipe数据types如何。 唯一需要改变的是比较函数,它不同于数据types和数据types。 因此qsort期望用户提供所述比较函数作为函数参数。

封装和抽象是相辅相成的,所以你可以说明它们是真正不可分割的。 实际上,这可能是真的; 这就是说,这是一个封装,这不是一个抽象:

 class point { numeric x numeric y } 

我们封装了这个点的坐标,但是我们并没有将它们实质地抽象出来,除了逻辑上的分组。

下面是一个不封装的抽象的例子:

 T pi<T> = 3.1415926535 

这是一个具有给定值(π)的通用variables pi ,声明并不关心variables的确切types。 无可否认,我很难在实际的代码中find这样的东西:抽象几乎总是使用封装。 然而,上面实际上存在于C ++(14)中,通过variables模板 (=variables的通用模板); 稍微更复杂的语法,例如:

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

封装隐藏了实现细节,这些实现细节可能是也可能不是通用的或专门的行为。

抽象是提供一个泛化(比如说,一组行为)。

这里有一个很好的解读:对象代理的Edward V. Berard的抽象,封装和信息隐藏 。

封装把一些东西放在一个盒子里,给你一个窥视孔; 这使你免受齿轮的污染。

抽象的扁平化忽略了无关紧要的细节,比如事物是否有齿轮,棘轮,飞轮或核心; 他们只是“走”

封装的例子:

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

抽象的例子:

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

许多答案和例子都是误导性的。

封装是将数据function操作数据 封装到单个组件中,并限制对某些对象组件的访问。
封装意味着对象的内部表示通常在对象定义之外隐藏起来。

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

封装:信息隐藏
抽象:执行隐藏

例:

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

foo类的任何对象的内部表示都隐藏在类外部。 – >封装。
foo对象的任何可访问成员(数据/函数)都是受限制的,只能由该对象访问。

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

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

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

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

  • 抽象让你专注于对象的作用,而不是它如何做
  • 封装意味着隐藏对象如何做某事的内部细节或机制。

就像当你开车时,你知道油门踏板是做什么的,但是你可能不知道它背后的过程,因为它是封装的。

让我举个例子在C#中。 假设你有一个整数:

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

你可以使用像Number.ToString()这样的方法来返回数字5的字符表示,并将其存储在string对象中。 该方法告诉你它做了什么,而不是它如何做。

抽象是概括的术语。 即封装是抽象的子集。

在这里输入图像描述

礼貌

封装 :隐藏对象的实际用户不需要的/不可预料的/适当的实现细节。 例如

 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** 

这些有些模糊的概念并不是计算机科学和编程独有的。 我想提供一些额外的想法,可以帮助他人理解这些重要的概念。


简答

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

抽象 – 除具体的实际情况,具体的对象或实际情况外,考虑除去某些特征的东西,从而降低复杂性。

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

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


长答案

封装

这里有一个封装的例子,希望能够让事情变得更加清晰:

Arduino封装

这里我们有一个Arduino Uno和一个Arduino Uno。 封装是关于封装的一个很好的代表。

封装旨在保护某些组件不受外界影响和知识的影响,并且暴露其他事物应该与之交互的组件。 在编程方面,这涉及通过访问修饰符 隐藏信息 ,这会改变某些variables和/或属性的读写范围。

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

在编程中,这涉及将各种组件分组为可分离的结构,例如functionclassobject 。 它还包括提供与这些构造进行交互的手段,以及获得有关这些构造的有用信息的方法。

封装帮助程序员有许多额外的方法,其中最重要的是改进了代码可维护性和可testing性。

抽象化

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

以下是我喜欢抽象的想法:

像素树

你会说那里有一棵树的形象吗? 有机会,你会的。 但是它真的是一棵树吗? 那当然不是! 这是一堆像素,看起来像我们可能称为一棵树。 我们可以说这是一个真正的树的抽象。 请注意,树的几个视觉细节被省略。 而且,它不会生长,不会消耗水分,也不会产生氧气。 怎么可能? 它只是一堆屏幕上的颜色,用计算机内存中的字节表示。

这就是抽象的本质。 这是一种简化事物的方式,使他们更容易理解。 头脑中的每一个想法都是对现实的抽象。 树的心像不像这个jpeg那样是一棵真正的树。

在编程中,我们可以通过创build一个Tree类,使用模拟生长,耗水和氧气生产的方法来利用这个优势。 我们的创作将代表我们对实际树木的体验,只包括我们真正关心的特定模拟元素。 我们使用抽象作为表示我们用字节和math的东西的一种方式。

抽象类

编程中的抽象也允许我们考虑几个“具体”对象types(实际存在的types)之间的共同性,并在一个独特的实体中定义这些共同性。 例如,我们的Tree类可以inheritance一个abstract class Plant ,它具有适用于我们所有植物类的几个属性和方法,但删除那些对于每种types的植物特定的属性和方法。 这可以显着减less重复的代码,并提高可维护性。

abstract class和普通class的实际区别在于概念上没有abstract class “真实”实例。 构build一个Plant对象是没有意义的,因为它不够具体。 每一个“真正”的Plant也是一个更具体的Planttypes。

另外,如果我们希望我们的程序更现实一些,我们可能要考虑一下,我们的Tree类可能太抽象了。 实际上,每个Tree都是一个更具体的Treetypes,所以我们可以创build类,如BirchMaple等,它们从我们现在abstract Tree类inheritance而来。

JVM

另一个很好的抽象例子是Java虚拟机(Java Virtual Machine,JVM) ,它为运行Java代码提供了一个虚拟或抽象的计算机。 它基本上带走了系统中所有特定于平台的组件,并提供了“计算机”的抽象接口,而不考虑任何系统。

区别

封装与抽象的不同之处在于它与“真实”或“准确”的东西没有任何关系。 它不删除某些东西的组成部分,以使其更简单或更广泛适用。 相反,它可能隐藏某些组件以达到类似的目的。

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

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

一个简单的例子就是定义一个私有variables,并使用getter和setter方法来访问它,或者使一个私有variables成为私有variables,因为它只能用于类。 用户不需要了解这些方法和variables。

注意 :封装只是数据隐藏,不应该被误解。 当我们说封装时,重点应该是将相关的数据和行为组合或打包在一起。

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

示例 –

比方说,我们有一个接口动物 ,它有一个函数makeSound() 。 有两个实现这个接口的具体类DogCat 。 这些具体的类有不同的makeSound()函数的实现。 现在让我们说我们有一个动物(我们从一些外部模块得到这个)。 所有的用户都知道它正在接收的对象是一些Animal,用户负责打印动物的声音。 一个蛮力的方法是检查收到的对象,以确定它的types,然后将其转换为该Animaltypes,然后调用 makeSound()。 但一个更好的方法是把事情抽象出来 。 使用Animal作为多态引用并调用makeSound()。 在运行时取决于什么是真正的对象types是正确的function将被调用。

更多细节在这里 。

在这里输入图像描述

复杂的逻辑是在封装在触摸板中的电路板中,并提供一个漂亮的界面(button)将其抽象出来给用户。

抽象:以简化/不同的方式呈现某些东西的想法,这种方式要么更容易理解,更要使用,或者与情况更为相关。

考虑一个发送电子邮件的类…它使用抽象来向你展示自己作为某种信使的孩子,所以你可以调用emailSender.send(邮件,收件人)。 它实际上做了什么 – selectPOP3 / SMTP,调用服务器,MIME翻译等,被抽象出来。 你只看到你的使者男孩。

封装(Encapsulation):保护和隐藏对象私有的数据和方法的思想。 它更多地处理独立和万无一失的事情。

拿我来说吧。 我从世界其他地方封装我的心率。 因为我不想让其他人改变这个variables,而且我也不需要其他的人来设置它来让我工作。 它对我来说非常重要,但是你不需要知道它是什么,反正你也可能不在乎。

环顾四周,你会发现几乎所有你碰到的东西都是抽象和封装的例子。 例如,你的手机给你提供了能够把你所说的话和其他人说出来的抽象概念 – 涵盖了GSM,处理器架构,无线电频率以及其他一些你不了解或关心的事情。 它还封装了您的某些数据,如序列号,身份证号码,频率等。

这一切都让这个世界变得更加美好:D

抽象和封装之间的区别。

抽象和封装之间的区别

抽象:只显示必要的信息。 我们来关注一下在电脑上打开的例子。 用户不必知道在系统还在加载的过程中发生了什么(该信息对用户是隐藏的)。

再举一个例子,那就是ATM。 客户不需要知道机器如何读取PIN并处理交易,他只需要inputPIN码,拿走现金就可以离开。

Encapsulation(封装):隐藏clas的敏感数据,从而将其中的一部分私有化。 这是一种通过不允许从外部访问的方式将一些信息保留给客户的方法。

另一个例子:

假设我创build了一个不可变的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_; } 

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

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

一个好的抽象的例子是一个通用的数据库连接类。 它的公共接口是与数据库无关的,并且非常简单,但是允许我按照我想要的方式来执行连接。 你看到了吗? 这里也有封装,因为这个类必须包含所有的底层处理和调用。

防止特定对象的数据被外部function故意或意外误用的机制称为“ 数据封装”

代表基本特征而不包括背景细节或解释的行为被称为抽象

使用一个简单的例子AbstractionEncapsulation

————————————————– ————————————————– ——————————–

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

图片

封装将复杂性封装在一个封装中,因此封装是封装…而抽象是与其他对象区分开的对象的特征。

抽象可以通过抽象抽象具有一个或多个方法来实现。 这只不过是阶级延伸的特点。 例如,当你发明/devise一辆汽车时,你定义了一个像汽车这样的特征,应该有4个车门,中断,方向盘等……所以任何使用这种devise的人都应该包含这个特征。 实现不是抽象的头脑。 它只会定义应包含的特征。

通过使用访问修饰符(如公共,私有,inheritance,聚合或组合)来实现封装。 所以你只显示所需要的东西,这也只是你想展示的程度。 即公共的,受保护的,友好的和私人的基础……例如,通用汽车决定使用上述汽车的抽象devise。 但他们有各种各样的产品具有相同的特点和function差不多。 所以他们写了一个扩展上面的抽象类的类。 它说什么齿轮箱应该如何工作,应该如何工作,方向盘应该如何工作。 那么所有的产品都使用这个通用的function。 他们不需要知道齿轮箱是如何工作的,或者是破坏工作或转向风车的工作。 个性化的产品可以肯定有更多的function,如空调或自动locking等.. ..

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

从这个

OOPS中封装与抽象的区别

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

封装与抽象的真实生活差异

封装意味着隐藏。 封装也被称为数据隐藏。你可以把封装看作封装在内部的胶囊(药片)。 封装是封装,只是隐藏属性和方法。 封装用于将代码和数据隐藏在一个单元中,以保护来自世界各地的数据。 类是封装的最好例子。

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

封装与抽象的实现差异

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

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

抽象:抽象意味着展现Whatfunction的一部分。

封装:封装意味着隐藏How部分的function。

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

 /// <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 } } 

Program class of Console Application

 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); } } 

Abstraction— Hiding Implementation–at Design—Using Interface/Abstract calsses

Encapsulation–Hiding Data –At Development—Using access modifiers(public/private)

Lets take the example of a stack. It could be implemented using an array or a linked list. But the operations it supports are push and pop. Now abstraction is exposing only the interfaces push and pop. The underlying representation is hidden(is it an array or is it a linked list?) and a well defined interface is provided. Now how do you ensure that no accidental access is made to the abstracted data? That is where the Encapsulation comes in. For eg classes in C++ use the access specifiers which ensure that accidental access and modification is prevented. And also by making the above mentioned interfaces as public, it ensures that the only way to manipulate the stack is through the well defined interface. In the process, it has coupled the data and the code that can manipulate it. ( Lets not get the friend functions involved here.). That is the code and data are bonded together or tied or encapsulated

Information hiding is not strictly required for abstraction or encapsulation. Information might be ignored, but does not have to be hidden.

Encapsulation is the ability to treat something as a single thing, even though it may be composed of many complex parts or ideas. For example, I can say that I'm sitting in a "chair" rather than referring to the many various parts of that chair each with a specific design and function, all fitting together precisely for the purpose of comfortably holding my butt a few feet away from the floor.

Abstraction is enabled by encapsulation. Because we encapsulate objects, we can think about them as things which relate to each other in some way rather than getting bogged down in the subtle details of internal object structure. Abstraction is the ability to consider the bigger picture, removed from concern over little details. The root of the word is abstract as in the summary that appears at the top of a scholarly paper, not abstract as in a class which can only be instantiated as a derived subclass.

I can honestly say that when I plop my butt down in my chair, I never think about how the structure of that chair will catch and hold my weight. It's a decent enough chair that I don't have to worry about those details. So I can turn my attention toward my computer. And again, I don't think about the component parts of my computer. I'm just looking at a part of a webpage that represents a text area that I can type in, and I'm communicating in words, barely even thinking about how my fingers always find the right letters so quickly on the keyboard, and how the connection is ultimately made between tapping these keys and posting to this forum. This is the great power of abstraction. Because the lower levels of the system can be trusted to work with consistency and precision, we have attention to spare for greater work.

I will try to demonstrate Encapsulation in a simple way.. Lets see..

  • The wrapping up of data and functions into a single unit (called class) is known as encapsulation. Encapsulation containing and hiding information about an object, such as internal data structures and code.

Encapsulation is –

  • Hiding Complexity,
  • Binding Data and Function together,
  • Making Complicated Method's Private,
  • Making Instance Variable's Private,
  • Hiding Unnecessary Data and Functions from End User.

Encapsulation implements Abstraction.

And Abstraction is –

  • Showing Whats Necessary,
  • Data needs to abstract from End User,

Lets see an example-

The below Image shows a GUI of "Customer Details to be ADD-ed into a Database".

Customer Screen GUI

By looking at the Image we can say that we need a Customer Class.

Step – 1: What does my Customer Class needs?

  • 2 variables to store Customer Code and Customer Name.
  • 1 Function to Add the Customer Code and Customer Name into Database.

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

Now only ADD method wont work here alone.

Step -2: How will the validation work, ADD Function act?

We will need Database Connection code and Validation Code (Extra Methods).

 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(); } } 

Now there is no need of showing the Extra Methods(Validate(); CreateDBObject() [Complicated and Extra method] ) to the End User.End user only needs to see and know about Customer Code, Customer Name and ADD button which will ADD the record.. End User doesn't care about HOW it will ADD the Data to Database?.

Step -3: Private the extra and complicated methods which doesn't involves End User's Interaction.

So making those Complicated and Extra method as Private instead Public(ie Hiding those methods) and deleting the obj.Validate(); obj.CreateDBObject(); from main in class Program we achieve Encapsulation.

In other words Simplifying Interface to End User is Encapsulation.

So now the code looks like as below –

 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(); } } 

总结:

Step -1: What does my Customer Class needs? is Abstraction.

Step -3: Step -3: Private the extra and complicated methods which doesn't involves End User's Interaction is Encapsulation.

PS – The code above is hard and fast.

 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** 

abstraction is hiding non useful data from users and encapsulation is bind together data into a capsule (a class). I think encapsulation is way that we achieve abstraction.

The below paragraph helped me to understand how they differ from each other:

Data encapsulation is a mechanism of bundling the data, and the functions that use them and data abstraction is a mechanism of exposing only the interfaces and hiding the implementation details from the user.

你可以在这里阅读更多。

Abstraction is a contract for the implementation we are going to do. Implementation may get changed over period of time. The various implementations themselves may or may not be hidden but are Masked behind the Abstraction.

Suppose we define all the APIs of a class in an interface then ask the users of our code to depened upon the defined APIs of the interface . We are free to improve or modify the implementation only we must follow the set contract. The users are not coupled with our implementation.

We EXPOSE all the NECESSARY Rules (methods) in abstraction , the implementation of the rules are left for the implementor entities, also the implemention is not part of the abstraction. Its just the signature and declaration what makes the abstraction.

Encapsulation is simply HIDING the internal details by reducing the acess of the states and behaviors. An encapsulated class may or may not have well defined Abstraction .

java.util.List is an abstraction for java.util.ArrayList . The internal states of java.util.ArrayList being marked with non public access modifiers is encapsulation.

Edit Suppose a class Container.nava implements IContainer , IContainer may declare methods like addElement , removeElements , contains , etc. Here IContainer represents the abstraction for its implementing class. Abstraction is declaring the APIs of the class or a module or a system to the outer world. These APIs become the contract . That system may be or may not be developed yet. The users of the system now can depend on the declared APIs and are sure any system implementing such a contract will always adhere to the APIs declared, they will always provide tge implementation for those APIs. Once we are writing some concrete entity then deciding to hide our internal states is encapsulation

Encapsulation require modularity. It requires you to create objects that has the data and the methods to process the data. In this case you can view it as a module.

Abstraction provides you a generalized view of your classes.

One could argue that abstraction is a technique that helps us identify which specific information should be visible, and which information should be hidden. Encapsulation is then the technique for packaging the information in such a way as to hide what should be hidden, and make visible what is intended to be visible.

The process of Abstraction and Encapsulation both generate interfaces.

An interface generated via encapsulation hides implementation details.

An interface generated via abstraction becomes applicable to more data types, compared to before abstraction.