抽象和封装的区别?

封装和抽象之间的确切区别是什么?

450753 次浏览

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

抽象提供了一个泛化(例如,对一组行为)。

这里有一个很好的阅读:抽象、封装和信息隐藏由Edward V. Berard的对象机构。

  • 抽象让您关注对象做了什么,而不是它是如何做的
  • 封装意味着隐藏对象如何做某事的内部细节或机制。

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

让我用c#举个例子。假设你有一个整数:

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

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

封装把一些东西放在一个盒子里,给你一个窥视孔;这使你从混乱与齿轮。

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

封装的例子:

  • 内裤
  • 工具箱
  • 钱包
  • 手提包
  • 胶囊
  • 冷冻carbonite
  • 一个盒子,上面有或没有按钮
  • 一个墨西哥卷饼(严格来说,是卷饼周围的玉米粉圆饼)

抽象的例子:

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

另一个例子:

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

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

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

一个好的抽象例子是通用数据库连接类。它的公共接口与数据库无关,非常简单,但允许我对连接做我想做的事情。你看到了吗?这里还有封装,因为类内部必须有所有低级句柄和调用。

封装:对对象的实际用户隐藏不需要的/不期望的/适当的实现细节。 例如< / p >

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

封装要求模块化。它要求您创建具有数据和处理数据的方法的对象。在这种情况下,您可以将其视为一个模块。

抽象为您提供了类的一般视图。

这里的大多数答案都关注于OOP,但封装开始得更早:

  • < p > 每个函数都是封装;在伪代码:

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

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

  • 抽象泛化的过程:采取具体的实现,并使其适用于不同的,尽管有些相关的数据类型。抽象的经典例子是C的qsort函数来排序数据:

    关于qsort的事情是,它并不关心它所排序的数据-事实上,它不知道它所排序的数据。相反,它的输入类型是一个无类型指针(void*),这只是C语言表示“我不关心数据的类型”的方式(这也称为类型擦除)。重要的一点是,不管数据类型是什么,qsort的实现总是保持不变。唯一要改变的是compare函数,它因数据类型的不同而不同。qsort因此期望用户提供上述比较函数作为函数参数

封装和抽象是密切相关的,因此您可以认为它们确实是不可分割的。就实际而言,这可能是对的;也就是说,这里有一个不太抽象的封装:

class point {
numeric x
numeric y
}

我们封装了点的坐标,但是我们没有实质性地将它们抽象出来,只是在逻辑上对它们进行分组。

这里有一个抽象的例子,它不是封装:

T pi<T> = 3.1415926535

这是一个具有给定值(π)的泛型变量 pi,声明并不关心变量的确切类型。诚然,我很难在真实的代码中找到这样的东西:抽象实际上总是使用封装。然而,上面的实际上存在于c++(14)中,通过< em > < / em >变量模板(=变量的通用模板);使用稍微复杂一点的语法,例如:

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

抽象:以一种简化的/不同的方式来呈现某事的想法,这种方式要么更容易理解和使用,要么更切合实际情况。

考虑一个发送电子邮件的类……它使用抽象来向你展示自己作为某种信使,所以你可以调用emailSender。发送(邮件,收件人)。它的实际功能——选择POP3 / SMTP、调用服务器、MIME转换等等,都被抽象了出来。你只看到你的信使。

封装:保护和隐藏对象私有的数据和方法的思想。它更多的是让某样东西独立且万无一失。

以我为例。我把我的心率从世界其他地方压缩起来。因为我不希望其他人改变这个变量,我也不需要其他人来设置它来让我运行。它对我来说至关重要,但你不需要知道它是什么,而且你可能根本不在乎。

环顾四周,您会发现几乎所有您接触到的东西都是抽象和封装的例子。例如,你的手机向你展示了一种抽象的功能,它能把你说的话传达给别人——掩盖了GSM、处理器架构、无线电频率以及其他无数你不理解或不关心的东西。它还封装了来自您的某些数据,如序列号、ID号、频率等。

这一切都使世界成为一个更美好的居住地

抽象:只显示必要的信息。让我们关注一下在计算机上进行开关的例子。当系统仍在加载时,用户不必知道发生了什么(该信息对用户隐藏)。

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

封装:处理隐藏类的敏感数据,因此私有化它的一部分。这是一种通过不允许外部访问来保持某些信息对其客户端的私密性的方法。

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个门、刹车、方向盘等,所以任何使用这种设计的人都应该包括这些特征。实现并不是抽象的首要部分。

封装是将数据和行为保存在一个胶囊中,这个胶囊是类&通过使用访问修饰符,如公共,私有,保护与继承,聚合或组合。所以你只显示需要的东西,也只显示到你想要显示的程度。即公共的,受保护的,友好的;私人ka funda...... 例:通用汽车公司决定采用上述汽车的抽象设计。但他们有各种各样的产品具有相同的特性&做几乎相同的功能。因此,他们编写了一个扩展上述抽象类的类。它说齿轮箱应该如何工作,刹车应该如何工作,方向盘应该如何工作。然后所有的产品都使用这个通用功能。他们不需要知道齿轮箱如何工作或打破工作或方向盘工作。独立产品肯定可以有更多的功能,如空调或自动锁等.....

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

抽象对用户隐藏无用的数据 封装是将数据绑定到一个胶囊(类)中。 我认为封装是我们实现抽象的方式

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

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

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

现在抽象只公开了push和pop接口。底层表示是隐藏的(它是数组还是链表?)并且提供了定义良好的接口。现在,如何确保不对抽象数据进行意外访问呢?这就是封装的用武之地。例如,c++中的类使用访问说明符来确保防止意外的访问和修改。而且,通过将上面提到的接口公开,可以确保操作堆栈的唯一方法是通过定义良好的接口。在这个过程中,它将数据和可以操作它的代码耦合起来(这里不涉及友元函数)。也就是说,代码和数据被绑定在一起或捆绑或封装。

Encapsulation .表示隐藏数据,比如使用getter和setter等。

抽象表示使用抽象类和接口等隐藏实现。

我认为封装是实现抽象的一种方式。看看下面的链接。

抽象与封装 .

< em > Abstraction < / em >< em > Encapsulation < / em >,使用一个通用的例子

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

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

image

抽象或封装并不严格要求信息隐藏。信息可能会被忽略,但不一定要隐藏。

例如,我可以说我坐在一把“椅子”上,而不是指那把椅子的许多不同部分,每个部分都有特定的设计和功能,所有这些部件都精确地装配在一起,目的是为了舒适地让我的屁股离地板几英尺远。

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

我可以诚实地说,当我扑通一声坐在椅子上时,我从来没有想过椅子的结构将如何抓住和承受我的重量。这把椅子够体面了,我不用担心那些细节。这样我就可以把注意力放在电脑上了。再说一次,我不考虑电脑的组成部分。我只是看着网页的一部分,它代表了我可以输入的文本区域,我用文字交流,几乎没有想过我的手指如何总是那么快地在键盘上找到正确的字母,以及点击这些键和在这个论坛上发帖之间的最终联系是如何形成的。这就是抽象的伟大力量。因为可以信任系统的较低级别以一致性和准确性工作,所以我们可以将注意力用于更大的工作。

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

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

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

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

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

一个简单的例子是定义一个私有变量,并使用getter和setter方法访问它,或者将一个方法设置为私有,因为它只在类中使用。用户不需要知道这些方法和变量。

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

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

的例子,

假设我们有一个接口的动物,它有一个函数makeSound ()。有两个具体的类实现了这个接口。这些具体类具有makeSound()函数的独立实现。现在假设我们有一个动物(我们从外部模块得到这个)。所有用户知道的是,它正在接收的对象是一些动物,这是用户的责任打印动物的声音。一个蛮力方法是检查接收到的对象识别它的类型,然后定型它的动物类型,然后调用 makeSound()在它上面。但更简洁的方法是抽象事物。使用Animal作为多态的参考并在其上调用makeSound()。在运行时,根据实际对象类型,将调用适当的函数。

更多细节在这里

enter image description here

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

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

OOPS中封装和抽象的区别

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

封装和抽象的现实区别

封装意味着隐藏。封装也称为数据隐藏。你可以把胶囊想象成胶囊(药片),里面藏着药。封装是包装,只是隐藏属性和方法。封装用于将代码和数据隐藏在单个单元中,以保护数据不受外界的影响。类是封装的最佳示例。

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

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

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

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

抽象和封装的区别。

抽象与封装的区别

我将尝试以一种简单的方式演示封装。让我们看看. .

  • 将数据和函数包装成一个单元(称为 类)被称为封装。封装、包含和隐藏 关于对象的信息,如内部数据结构和 李代码。< / >

封装是-

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

封装实现了抽象。

抽象就是——

  • 显示什么是必要的,
  • 数据需要从最终用户,

让我们看一个例子

下图显示了“将客户详细信息添加到数据库”的图形用户界面。

Customer Screen GUI

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

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

即。

  • 2个变量来存储客户代码和客户名称。
  • 1将客户代码和客户名称添加到数据库。

    CustomerContent < p >名称空间 { 公共类客户 { CustomerCode = ""; CustomerName = ""; 公共无效ADD() { //我的DB代码会在这里 李}< / p > < / >

现在只有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();
}
}

现在不需要显示额外的方法(Validate();CreateDBObject()[复杂和额外的方法])给最终用户。最终用户只需要看到和知道客户代码,客户名称和ADD按钮,这将添加记录。最终用户不关心如何将数据添加到数据库?

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

所以使那些复杂的和额外的方法为私有而不是公共(i。e隐藏这些方法),并删除obj.Validate();obj.CreateDBObject ();从主类程序中实现封装。

换句话说,将接口简化为终端用户就是封装。

现在代码如下所示

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:封装不涉及最终用户交互的额外和复杂的方法。

附注:上面的代码是硬而快速的。

许多答案和例子都具有误导性。

封装是将“data"“在该数据上操作的函数”;打包成一个组件,并限制对对象的某些组件的访问。
封装意味着对象的内部表示通常隐藏在对象定义之外的视图中

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

< p > 封装:——信息隐藏
抽象:< / em >——实现隐藏

示例(c++):

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的实现是隐藏的。——比;抽象

两者之间存在差异

ABSTRAACTION

而且

封装

1.    First difference between Abstraction and Encapsulation is that, Abstraction is implemented in Java using interface and abstract class while Encapsulation is implemented using private, package-private and protected access modifier.


2.    Data abstraction simply means generalizing something to hide the complex logic that goes underneath where Encapsulation is DATA HIDING.




3.    Encapsulation is combining related logic data (variables and methods) where as Abstraction is hiding internal implementation details and expose only relevant details to the user. In a way you can Abstraction is achieved by Encapsulation.

enter image description here

简而言之

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

< p > 数据隐藏是封装的一个子集封装是Abstraction的子集

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

抽象:抽象意味着显示功能的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);
}
}

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

抽象 封装
它解决了设计层面的问题。 封装解决了实现级的问题。
隐藏不必要的细节,但显示必要的信息。 它将代码和数据隐藏到单个实体或单元中,这样数据就可以不受外界的影响。
专注于外部的观察。 注重内部工作。
让我们关注对象做了什么,而不是它是如何做的。 让我们关注对象是如何做某事的。
例如:手机的外观,就像它有一个显示屏和按钮。 例如:手机内部细节,按键和显示屏如何通过电路相互连接。
人力资源/ > < / div > < 例子:解决方案架构师是创建整个解决方案的高级摘要技术设计的人,然后这个设计移交给开发团队进行实现
在这里,解决方案架构师充当抽象,开发团队充当封装

举例:用户数据的封装(组网)

enter image description here

图片提供

类型使程序员能够在比位或字节更高的级别上思考,而不必为低级的实现而烦恼。例如,程序员可以开始将字符串看作一组字符值,而不仅仅是一个字节数组。更重要的是,类型使程序员能够考虑和表达任意大小的两个子系统之间的接口。这使更多级别的本地化成为可能,以便在两个子系统通信时,子系统互操作性所需的定义保持一致。 < / p >

Java示例 . sh Java示例

抽象—隐藏实现—在设计—使用接口/抽象类

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

封装是抽象的一个例子。封装的全部意义在于抽象函数内部发生的事情,将所有的复杂性简化为一个符号(函数的引用或名称),将函数变成一个黑盒。

在编程中,“抽象”一词是一个命令。当一个类继承了一个抽象类(或接口)时,您将被命令创建一个抽象。

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


简短的回答

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

抽象 -从具体的现实、具体的对象或实际实例中去除某些特征,从而降低复杂性。

主要的相似是这些技术以提高理解能力和实用性为目标。

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


长回答

封装

下面是一个封装的例子,希望能让大家更清楚:

Arduino封装

这里我们有一个Arduino Uno,和一个Arduino Uno在一个外壳。封装是封装的一个很好的代表。

封装旨在保护某些组件不受外部影响和知识的影响,并公开其他组件应该与之交互的组件。在编程术语中,这涉及到信息隐藏<强> < / >强< >强访问修饰符< / >强,它们改变了某些变量和/或属性可以读写的程度。

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

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

封装在许多其他方面帮助程序员,尤其是提高代码的可维护性和可测试性。

抽象

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

以下是我对抽象的看法:

像素树

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

这就是抽象的本质。这是一种简化事物的方法,这样它们就更容易理解。你脑子里的每一个想法都是对现实的抽象。你脑海中的树和这张图片一样都不是真正的树。

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

抽象类

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

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

另外,如果我们想让程序更现实,我们可能需要考虑Tree类本身可能太抽象了。实际上,每个Tree都是更具体的Tree类型,因此我们可以为这些类型创建类,例如BirchMaple等,它们继承自我们的abstractTree类。

JVM

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

的区别

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

有一件事,也许是其他答案忘记提到的一个基本的事情是,封装IS抽象。因此,对比两者并寻找差异是不准确的,而是要看封装是抽象的一种形式

下面这段话帮助我理解了它们之间的区别:

数据封装是一种将数据捆绑的机制 使用它们的函数和数据抽象是一种机制 只暴露接口,隐藏实现细节

.

.

你可以阅读更多在这里

我试图在抽象和封装之间画一条线,根据我的观点,抽象更多的是概念性的东西,而封装是抽象实现的一种。因为一个人可以隐藏数据而不封装,例如使用私有常数或变量;所以我们可以有带有数据隐藏的封装,但数据隐藏并不总是封装。在下面这段代码中,我试图描述这些概念的最简单形式。

    // Abstraction
interface IOperation
{
int SquareNumber();
}


public class Operation
{
// Data hiding
private int number;


public Operation(int _number)
{
this.number = _number;
}


// Encapsulation
public int SquareNumber()
{
return number * number;
}
}

在行动,

IOperation obj = new Operation(2);
// obj.number  <--- can't access because hidden from world using private access modifier but not encapsulated.
obj.SquareNumber(); // cannot access internal logic to calculate square because logic is hidden using encapsulation.

Abstraction是我们将要执行的实现的合同。实现可能会在一段时间内发生变化。各种实现本身可能隐藏,也可能不隐藏,但在抽象后面是戴面具的

假设我们在interface中定义了类的所有APIs,然后要求代码的用户依赖于interface中定义的APIs。我们可以自由地改进或修改实现,但必须遵守设定的合同。在我们的实现中,用户不是耦合

我们在抽象中公开所有必要的规则(方法),规则的实现留给实现者实体,实现也不是抽象的一部分。它只是签名宣言使抽象。

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

java.util.Listjava.util.ArrayList的抽象。用non public访问修饰符标记的java.util.ArrayList的内部状态是封装。

<强>编辑 假设一个类Container.nava implements IContainerIContainer可以声明类似addElementremoveElementscontains等方法。这里IContainer表示其实现类的抽象。抽象是向外界声明类、模块或系统的api。这些api成为contract。 这个系统可能已经开发出来,也可能还没有开发出来。系统的用户现在可以依赖于声明的api,并确保任何实现这样一个契约的系统将始终坚持声明的api,他们将始终为这些api提供实现。一旦我们写了一些具体的实体,然后决定隐藏我们的内部状态是封装

让我用简单的代码示例来尝试一下

抽象=数据隐藏+封装

 // Abstraction
interface IOperation
{
int GetSumOfNumbers();
}
internal class OperationEven : IOperation
{
// data hiding
private IEnumerable<int> numbers;


public OperationEven(IEnumerable<int> numbers)
{
this.numbers = numbers;
}
// Encapsulation
public int GetSumOfNumbers()
{
return this.numbers.Where(i => i % 2 == 0).Sum();
}
}

抽象和封装都是用来隐藏数据的。但是有很大的不同。

封装

封装是将数据和对数据进行操作的代码绑定或包装成一个称为Class的单元的过程。

封装在实现级别解决了问题。

在类中,可以使用私有或受保护的访问修饰符来隐藏数据。

抽象

抽象是隐藏无关细节的概念。换句话说,通过对用户隐藏不必要的细节,使复杂的系统变得简单。

抽象在设计层面解决了问题。

可以通过在Java中创建接口和抽象类来实现抽象。

在ruby中,你可以通过创建模块来实现抽象。

示例:我们使用(收集,映射,减少,排序…)方法的枚举模块与数组和ruby哈希。

简而言之:

抽象是一种帮助我们识别哪些特定信息是必要的,哪些信息应该隐藏的技术。

因此,封装是一种以隐藏对象的细节和实现细节的方式封装信息的技术。

抽象

抽象是提取所有现有和可预见实现的公共属性和字段的过程。

例如< p >: 是轿车,掀背车,SUV,双门跑车,敞篷车的抽象。 Car将具有所有类型的汽车的所有属性和字段。

封装

封装是对用户隐藏不需要的细节的过程。这个术语来自于胶囊。就像药物隐藏在胶囊里一样。各种机器和设备和设备的细节,从搅拌机,自行车,洗衣机,收音机,电视到飞机。您不希望用户可以看到机器的所有细节。

在编程方面: 让我们考虑一个等级汽车。 在下面的例子中,所有用户需要知道的是转动键(turnKey()方法),他不知道内部函数。

.用户不需要知道任何内部函数或内部组件

在这种情况下,所有的私有方法都是内部函数,像“活塞p1”这样的私有字段是用户不需要知道的内部数据。

public class Car{


private void startMotor(){ //do something }
private void generateVoltage(){ //do something }
private void sparkPlugIgnition(){ //do something }
private void fuelFlowFromTankToInjector(){ //do something }
private void pushPistonsDown() {
p1.doAction();
p2.doAction();
//do something    }
private void moveCrankShaft(){ //do something }


private Piston p1;
private Piston p2;


public void turnKey(){
startMotor();
generateVoltage();
sparkPlugIgnition();
fuelFlowFromTankToInjector();
pushPistonsDown();
moveCrankShat();
...
}
}

我读得越多,就越困惑。所以,我的理解是:

封装:

我们通常从外面看到手表,它的组件被封装在它的身体里。我们对不同的操作有某种控制。这种隐藏细节和公开控制(例如设置时间)的方式就是封装。

抽象:

到目前为止,我们一直在谈论手表。但我们没有具体说明是哪种手表。可以是数字的,也可以是模拟的,可以是手用的,也可以是墙用的。有很多可能性。我们所知道的是,这是一块手表,它显示时间,这是我们唯一感兴趣的东西,时间。这种隐藏细节和公开通用特性或用例的方法就是抽象。