封装和抽象之间的确切区别是什么?
当前回答
我试图在抽象和封装之间画一条线,根据我的观点,抽象更多的是概念性的东西,而封装是抽象实现的一种。因为一个人可以隐藏数据而不封装,例如使用私有常数或变量;所以我们可以用数据隐藏进行封装,但数据隐藏并不总是封装。在下面这段代码中,我试图描述这些概念的最简单形式。
// 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.
其他回答
上面提供了很多很好的答案,但我将在这里介绍我的(Java)观点。
数据封装简单地说就是包装和控制类中逻辑分组数据的访问。它通常与另一个关键字-数据隐藏相关联。这是在Java中使用访问修饰符实现的。
一个简单的例子是定义一个私有变量,并使用getter和setter方法访问它,或者将一个方法设置为私有,因为它只在类中使用。用户不需要知道这些方法和变量。
注意:不要误解封装只是关于数据隐藏。当我们说封装时,重点应该是将相关数据和行为分组、打包或捆绑在一起。
另一方面,数据抽象是泛化的概念,这样底层的复杂逻辑就不会暴露给用户。在Java中,这是通过使用接口和抽象类实现的。
的例子,
Lets say we have an interface Animal and it has a function makeSound(). There are two concrete classes Dog and Cat that implement this interface. These concrete classes have separate implementations of makeSound() function. Now lets say we have a animal(We get this from some external module). All user knows is that the object that it is receiving is some Animal and it is the users responsibility to print the animal sound. One brute force way is to check the object received to identify it's type, then typecast it to that Animal type and then call makeSound() on it. But a neater way is to abstracts thing out. Use Animal as a polymorphic reference and call makeSound() on it. At runtime depending on what the real Object type is proper function will be invoked.
详情请点击这里。
复杂的逻辑是在电路板中,封装在一个触摸板中,并提供了一个漂亮的界面(按钮)来将其抽象给用户。
附注:以上链接是我的个人博客。
这里的大多数答案都关注于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};
许多答案和例子都具有误导性。
封装是将“数据”和“对该数据进行操作的函数”打包到单个组件中,并限制对某些对象组件的访问。 封装意味着对象的内部表示通常隐藏在对象定义之外的视图中。
抽象是一种表示基本特性而不包括实现细节的机制。
封装:——信息隐藏。 抽象:——实现隐藏。
示例(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对象的任何可访问成员(data/function)都是受限的,只能由该对象访问。
foo foo_obj(3, 4);
int sum = foo_obj.add();
方法add的实现是隐藏的。——>抽象。
封装意味着隐藏数据,比如使用getter和setter等。
抽象意味着-隐藏实现使用抽象类和接口等。
封装要求模块化。它要求您创建具有数据和处理数据的方法的对象。在这种情况下,您可以将其视为一个模块。
抽象为您提供了类的一般视图。