79

学习 OOP 概念,对深入理解抽象和封装特别感兴趣。

已经查看了以下内容

抽象 VS 信息隐藏 VS 封装

抽象和封装的区别?

如果没有一个真实而简单的示例类/代码片段,我发现很难理解这些概念。

我的一位同事说抽象只不过是创建抽象类和普通类,用范围保护其成员变量称为封装。

有没有一种简单的方法可以让我理解并帮助其他人理解它们到底是什么,而不是重复以下内容?

抽象和封装是互补的概念:抽象关注对象的可观察行为……封装关注引起这种行为的实现……封装通常通过信息隐藏来实现,即隐藏所有信息的过程不影响其本质特征的对象的秘密。

4

16 回答 16

176

抽象是一个过程,您只显示“相关”数据并“隐藏”用户不必要的对象细节。以您的手机为例,您只需要知道要按下哪些按钮来发送消息或拨打电话,按下按钮时会发生什么,您的消息是如何发送的,您的电话是如何连接的,这些都从用户。

封装是将数据和函数组合成一个称为类的单元的过程。在Encapsulation中,不直接访问数据;它是通过类中存在的函数访问的。简而言之,类的属性保持私有,并提供公共 getter 和 setter 方法来操作这些属性。因此,封装使数据隐藏的概念成为可能。

在此处输入图像描述

于 2014-04-12T15:07:14.110 回答
30

抽象是隐藏信息或仅向客户提供必要的细节。

例如汽车刹车——你只知道踩下踏板会使车辆停下来,但你不需要知道它在内部是如何工作的。

抽象的优势明天如果制动实现从鼓式制动器更改为盘式制动器,作为客户端,您无需更改(即您的代码不会更改)

封装是将数据和行为绑定在一个单元中。它也是一种语言机制,用于限制对某些组件的访问(这可以通过私有、受保护等访问修饰符来实现)

例如,具有属性(即数据)和行为(即对该数据进行操作的方法)

于 2013-04-15T11:49:13.510 回答
16

使用 C# 的示例

//abstraction - exposing only the relevant behavior
public interface IMakeFire
{
     void LightFire();
}

//encapsulation - hiding things that the rest of the world doesn't need to see
public class Caveman: IMakeFire
{
     //exposed information  
     public string Name {get;set;}

     // exposed but unchangeable information
     public byte Age {get; private set;}

     //internal i.e hidden object detail. This can be changed freely, the outside world
     // doesn't know about it
     private bool CanMakeFire()
     {  
         return Age >7;
     }

     //implementation of a relevant feature
     public void LightFire()
     {
        if (!CanMakeFire())
        {
           throw new UnableToLightFireException("Too young");
        }
        GatherWood();
        GetFireStone();
        //light the fire

     }

     private GatherWood() {};
     private GetFireStone();
}

public class PersonWithMatch:IMakeFire
{
      //implementation
 }

任何穴居人都可以生火,因为它实现了IMakeFire的“功能”。拥有一组火制造者(列表),这意味着 Caveman 和 PersonWithMatch 都是有效的选择。

这意味着

  //this method (and class) isn't coupled to a Caveman or a PersonWithMatch
  // it can work with ANY object implementing IMakeFire
  public void FireStarter(IMakeFire starter)
  {
        starter.LightFire();
    }

因此,您可以拥有许多具有大量细节(属性)和行为(方法)的实现者,但在这种情况下,重要的是他们的发火能力。这是抽象。

由于生火需要一些步骤(GetWood 等),因此这些步骤是隐藏在视图中的,因为它们是班级的内部关注点。穴居人还有许多其他可以被外界称为的公共行为。但是一些细节总是会被隐藏,因为与内部工作有关。它们是私有的,只为对象而存在,它们从不暴露。这是封装

于 2013-04-15T13:16:01.857 回答
9

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

抽象是管理复杂系统的强大方法。抽象由定义明确的对象及其层次分类管理。

例如,汽车本身就是一个定义明确的对象,它由其他几个较小的对象组成,例如齿轮系统、转向机构、发动机,它们又拥有自己的子系统。但是对于人类来说,汽车是一个单一的对象,可以通过其子系统的帮助进行管理,即使它们的内部细节是未知的。 礼貌


封装:将数据成员和方法一起包装成一个单元(即类)称为封装。

封装就像封装在一个胶囊中。也就是将与一个对象相关的相关操作和数据封装到该对象中。

封装就像你的包,你可以把你的笔、书等放在里面。这意味着这是封装成员和函数的属性。

class Bag{
    book;
    pen;
    ReadBook();
}

封装意味着隐藏对象的内部细节,即对象如何做某事。

封装防止客户看到其内部视图,其中实现了抽象的行为。

封装是一种用于保护对象中的信息不受其他对象影响的技术。

隐藏数据以确保安全,例如将变量设为私有,并公开属性以访问将公开的私有数据。

因此,当您访问该属性时,您可以验证数据并进行设置。 礼貌

于 2015-07-16T10:11:15.297 回答
8

抽象是一种隐藏细节以简化界面的方法。

因此,以汽车为例,汽车中的所有控件都是抽象的。这使您可以在不了解转向、加速或减速系统的基本细节的情况下操作车辆。

一个好的抽象是对一个接口进行广泛标准化的抽象,跨越类似问题的多个实例。一个伟大的抽象可以改变一个行业。

现代方向盘、制动踏板和油门踏板都是伟大抽象的例子。汽车转向最初看起来更像是自行车转向。刹车和油门都是手动操作的。但是我们今天使用的抽象是如此强大,它们席卷了整个行业。

--

封装是一种隐藏细节的方法,以保护它们免受外部操纵。

封装可以防止驾驶员操纵汽车的驾驶方式——从转向、悬架和制动的刚度,到油门和变速箱的特性。大多数汽车不提供用于更改任何这些内容的接口。这种封装可确保车辆按照制造商的预期运行。

一些汽车提供少量的驾驶模式——如豪华、运动和经济——允许驾驶员同时改变其中的几个属性。通过提供驾驶模式,制造商允许驾驶员对体验进行一些控制,同时防止他们选择会使车辆不那么愉快或不安全的属性组合。通过这种方式,制造商隐藏了细节以防止不安全的操作。这是封装。

于 2019-01-04T08:11:25.717 回答
5

好吧,我将用一个真实世界的例子来解释抽象。假设在您家中您确实有一个电插头,并且许多设备可以连接到同一个插头,但插头永远不会知道它连接到哪个设备,换句话说,设备的详细信息被抽象(隐藏)到了插头。

想想如果我们将设备直接连接到没有插头的电线上会怎样?假设将灯泡直接连接到电线,然后电线知道它连接到哪个设备以及何时需要更换灯泡,然后我们必须从灯泡上移除电线连接,这意味着灯泡与电线紧密耦合。换句话说,灯泡和电线知道它所连接的细节,意味着没有抽象。

在面向对象的世界中,抽象的工作方式完全相同。使用其他类函数/属性的类不需要知道它正在使用哪些类函数/属性,并且应该使用接口/抽象类抽象所有内容。

让我编写相同的示例。这里我有一个类“ElectricPlug”,它正在运行一个设备。但是“ElectricPlug”类不知道它正在运行哪个设备。它可以是任何实现接口“IDevice”的类,这意味着“RunDevice”的实现是从“ElectricPlug”中抽象出来的。这是完整的示例代码,

class Program
{
    static void Main(string[] args)
    {
        ElectricPlug electricPlug = new ElectricPlug(new Bulb());
    }
}

public class ElectricPlug
{
    private readonly IDevice _device;
    public ElectricPlug(IDevice device)
    {
        _device = device;
    }

    public void Run()
    {
        _device.Rundevice();
    }
}


public interface IDevice
{
    void Rundevice();
}


public class Bulb : IDevice
{
    public void Rundevice()
    {
       Console.WriteLine("Switched on bulb");
    }
}
于 2017-05-30T13:12:22.663 回答
4

抽象是您从您计划在设计中捕获/表示的实体中“丢弃”不必要的细节并仅保留与您的域相关的实体属性的过程。
示例:要代表汽车,您将保留例如型号和价格、当前位置和当前速度,而忽略颜色和座位数量等。

封装是属性和在单个抽象单元(即类)中操作它们的操作的“绑定”。
因此,汽车将具有accelarate stop操纵位置和当前速度等的功能。

于 2013-04-15T11:48:57.683 回答
3

封装就是它听起来的样子,一种在某物周围放置一个盒子以保护其内容的方式。抽象是提取某物的功能属性,这样您就可以仅使用提取的内容执行操作,而无需了解内部工作原理。

当我们说两种物质是液体时,我们使用“液体”作为我们选择讨论的那些物质的属性的抽象。这种抽象告诉我们,鉴于我们之前对液体的经验,我们可以用这些物质做些什么。

抽象也与层次结构没有任何关系。你可以有另一个抽象,比如“金属”,它以不同的方式提取物质的特性。

抽象会忘记细节,因此如果您使用特定的抽象,则不应询问抽象未授予的底层物质的属性。就像如果你把牛奶和水混合在一起,你很难问你有多少牛奶。

Functor 是对具有某种映射概念的事物的抽象,也就是说,您可以在其内部内容上运行一个函数,将内部位转换为其他任何内容。外部的东西保持相同的东西。

这很有用的地方是,如果你有一个在 Lists 上工作的函数,并且你意识到你只依赖于 map 接口,你可以改为依赖 Functor,然后你的函数可以与流、promise、maybes、元组和任何其他共享该抽象的东西。

像 Haskell 这样的函数式语言具有一些非常强大的抽象能力,这使得极端代码重用变得实用。

于 2017-06-02T04:04:46.403 回答
2

抽象就像使用计算机。

除了通过 GUI(图形用户界面)和外部硬件(例如屏幕)看到的内容之外,您完全不知道它发生了什么。所有那些漂亮的颜色等等。作为普通消费者,您只会看到与您相关的详细信息。

封装隐藏无关细节的实际行为。

您使用您的计算机,但您看不到它的 CPU(中央处理单元)是什么样的(除非您试图闯入它)。它隐藏(或封装)在所有铬和塑料后面。

在 OOP(面向对象编程)语言的上下文中,您通常有这种设置:

CLASS {
  METHOD { 
    *the actual code*
  }
}

“封装”的一个例子是有一个普通用户看不到的方法(私有)。“抽象”是普通用户使用他们可以(公共)以使用私有方法的方法。

于 2018-03-16T19:14:36.927 回答
1

数据抽象:访问任何类的数据成员和成员函数都简单地称为数据抽象......

封装:绑定变量和函数或 1 可以说数据成员或成员函数都在一个单元中称为数据封装....

于 2013-07-03T09:08:48.750 回答
1

封装可以被认为是用于将数据绑定在一起的包装纸,并作为一个单独的单元来保护它免受各种外部污垢的影响(我的意思是外部功能)。

抽象涉及缺乏细节和使用简单的界面来控制复杂的系统。

例如,我们可以通过按下按钮来点亮灯泡,而不用担心底层的电气工程(抽象)。

但是,您不能以任何其他方式点亮灯泡。(封装)

于 2016-08-25T02:34:57.283 回答
0

数据抽象:DA 只是过滤具体项目。通过类我们可以实现纯粹的抽象,因为在创建类之前我们可以只考虑类的相关信息。

封装:这是一种机制,通过它我们可以保护我们的数据免受外部影响。

于 2015-01-07T13:48:51.533 回答
0
public abstract class Draw {
    public abstract void drawShape(); // this is abstraction.  Implementation detail need not to be known.
    // so we are providing only necessary detail by giving drawShape(); No implementation. Subclass will give detail.


    private int type;    // this variable cannot be set outside of the class. Because it is private.
    // Binding private instance variable with public setter/getter method is encapsulation 

    public int getType() { 
        return type;
    }

    public void setType(int type) {  // this is encapsulation. Protecting any value to be set.
        if (type >= 0 && type <= 3) {
            this.type = type;
        } else {
            System.out.println("We have four types only. Enter value between 0 to 4");
            try {
                throw new MyInvalidValueSetException();
            } catch (MyInvalidValueSetException e) {
                e.printStackTrace();
            }

        }
    }
}

Abstraction与实现细节未知的方法有关,这是一种实现隐藏。
Encapsulation与实例变量绑定与方法有关,一种数据隐藏。

于 2013-04-15T11:53:38.870 回答
0

抽象是向用户显示必要的信息,而封装则向用户隐藏不需要的数据(来自用户的产品)。

封装实现了抽象。

抽象是封装实际实现它的过程。 例如。 添加用户逻辑-> 我们需要验证用户,创建数据库连接并插入用户。所以用户不知道需要调用验证函数,创建数据库连接,然后将值插入数据库。他只调用 AddUser 函数,该函数用 in 调用内部所有逻辑,这只是封装(对功能进行分组并隐藏方法)。

于 2019-02-13T13:33:17.723 回答
0

封装:我认为这与如何将事物绑定到一个实体而不是隐藏有很大关系。如果你选择隐藏你可以隐藏的东西。

抽象:抽象与隐藏的东西有很大关系,可以有不同的抽象级别。例如,在功能抽象中,我们可能会说能够将项目添加到列表中很重要,但如何完成的细节并不重要,应该隐藏起来。使用数据抽象,我们会说列表是我们可以存储信息的地方,但是列表的实际实现方式(例如,作为数组或作为一系列链接位置)并不重要,应该隐藏。

参考

于 2019-09-19T04:48:34.070 回答
0

抽象——用简单的话来说,抽象可以说是一种让用户远离某些系统的复杂细节或详细工作的方法。您也可以将其视为解决设计和界面级别任何问题的简单方法。

您可以说抽象的唯一目的是隐藏可能使用户感到困惑的细节。所以为了简化的目的,我们可以使用抽象。抽象也是面向对象编程的一个概念。它隐藏了实际数据,只显示了必要的信息。例如,在 ATM 机中,您不知道它在内部是如何工作的。只有您关心使用 ATM 接口。所以这可以被认为是一种抽象过程。

封装——封装也是面向对象编程的一部分。在这种情况下,您所要做的就是将数据和代码打包在一起,以便它们可以作为一个单元工作。它在实施级别起作用。它还提高了应用程序的维护性。

封装侧重于将保存信息的过程。在这里,您必须保护您的数据不被外部使用。

于 2020-12-23T17:41:39.643 回答