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


当前回答

另一个例子:

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

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

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

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

其他回答

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

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

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

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

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

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

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

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

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

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

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

Every function is an encapsulation; in pseudocode: point x = { 1, 4 } point y = { 23, 42 } numeric d = distance(x, y) Here, distance encapsulates the calculation of the (Euclidean) distance between two points in a plane: it hides implementation details. This is encapsulation, pure and simple. Abstraction is the process of generalisation: taking a concrete implementation and making it applicable to different, albeit somewhat related, types of data. The classical example of abstraction is C’s qsort function to sort data: The thing about qsort is that it doesn't care about the data it sorts — in fact, it doesn’t know what data it sorts. Rather, its input type is a typeless pointer (void*) which is just C’s way of saying “I don't care about the type of data” (this is also called type erasure). The important point is that the implementation of qsort always stays the same, regardless of data type. The only thing that has to change is the compare function, which differs from data type to data type. qsort therefore expects the user to provide said compare function as a function argument.

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

class point {
    numeric x
    numeric y
}

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

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

T pi<T> = 3.1415926535

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

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

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

封装:

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

抽象:

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