什么是封装?它是如何实际隐藏数据的?

时间:2011-04-15 07:48:55

标签: .net oop design-patterns encapsulation hidden-field

搜索提出了一个简单的定义:数据隐藏。

但是,请考虑以下两个例子:

1)第一个例子:

Class Employee
{
    public int age;
}

2)第二个例子:

Class Employee
{
    private int age;

    public int getAge(){return age;}
}

问题:
在上述两个示例中,都没有数据隐藏,因为age要么被其他人修改,要么被其他人查看。数据隐藏在哪里?封装如何帮助上述例子?

7 个答案:

答案 0 :(得分:25)

数据隐藏。第二个示例隐藏 值的存储方式。此外,第二个示例使该值对于类外的代码是只读的。通过拥有私有字段并通过方法或属性公开它们,您可以立即获得一些优势,其中一些优点是:

  • 访问控制粒度;您可以选择将值公开为只读,读写或只写。
  • 在存储值之前验证输入的可能性
  • 添加日志记录或其他审核机制的可能性

请注意,封装不仅仅是有访问控制。封装的主要用途是隐藏调用代码的实现细节。当调用代码想要检索值时,它不应该依赖于从哪里值。在内部,类可以将值存储在字段中,或者从某些外部资源(例如文件或数据库)中检索它。 也许该值不会存储在所有中,而是即时计算。这与调用代码无关。

当您通过方法或属性公开值时,您可以屏蔽调用此类详细信息的代码,这也使您可以更改实现,而不会影响调用代码。

答案 1 :(得分:3)

封装将 的内容的概念与如何实现区分开来。

封装是面向对象编程中非常重要的概念。它隐藏了应用程序中其他模块的数据。在您的示例2中,正如您所看到的那样,您只能使用getter方法获取年龄,但是您只能将值设置为该类中的私有成员而不是在其外部。这是封装的优势。

答案 2 :(得分:2)

想想这个变种:

class Employee
{
    private int _age;

    public string Age
    {
        get { return _age.ToString(); }
    }
}

在你的例子中,外部和内部使用整数,这是令人困惑的。 (类似于显示2 * 2 = 4来解释乘法而忘记2 + 2 = 4)

答案 3 :(得分:1)

Encapsulation只是data hiding

让我们看看封装是如何发生的。 假设您创建一个Employee类并包含两个实例变量。姓名和工资。你不要把它们变成私人的。现在,如果员工类创建了一个对象,程序中的另一个类可以访问这两个变量。所以我们想要的是将这两者或工资信息隐藏到外部类。

如果我们想要隐藏薪水我们可以简单地将薪水声明为private变量。现在我们知道甚至另一个类创建一个对象并尝试访问工资,因为它不起作用。因为它是一个私有字段,只能由Employee类访问。现在我们隐藏了我们的数据。

但假设我们需要一个人输入每个员工的薪资详情。 我会说得更清楚。 输入人员的数据有3种类型的数据要输入woked_hours, OT and leaves(Emplyee类有三个变量)。 我们希望此人输入这些详细信息,但我们do not wantsee salary calculation如何完成。它是根据Employee类中的数学方程式完成的。

所以他无法计算并输入自己的薪水。但是我们让他看看最后的薪水。那里我们创建一个方法来获取员工类内薪水的价值。它是

public int getSalary()
{
   return salary;
} 

他知道这一点,他可以使用两种方法来访问这些隐藏的字段。 set method and get method.所以他call getmethod.can see salary e.setSalary(1000);信息。因为我们已经创建了getMethod来返回薪水。现在他尝试使用set方法输入新的工资金额来改变工资的当前值。所以他打电话给 public void setSalary(int newSalary) { salary=newSalary; } 但是它给出了一个错误。为什么?因为在employee类中没有写为

的方法
Read only

我们故意不编写该代码,因为我们不希望他立即设置工资值。所以我们隐藏了一些信息,但有些信息仍让他访问。我们允许他访问not Write。但set为薪水。

因此,我们已经完成了封装,所以它不是很有用。

与允许他woked_hours, OT and leaves这些字段getter methods的方式相同。对于那些字段,我们已授予他访问权限的权限。我们故意不写​​getter。如果您同时写READ/ Write和setter,则允许他getters同时访问。

仅设置或获取无关紧要,该字段为私有,字段隐藏已隐藏数据。但有些访问是通过setters和{{1}}提供的。

答案 4 :(得分:0)

在您的第一个示例中,变量age被设置为公共变量。这里任何人都可以在声明Employee类型的对象时修改meeber年龄。

但是,在您的第二个示例中,变量age实际上是私有的,并且只能从Employee类内部进行修改。这就是数据隐藏的情况。

在面向对象的编程中,封装是指一个对象由另一个对象组成。这与对象可以扩展已存在的类的继承形成对比。

答案 5 :(得分:0)

封装比数据隐藏更多。封装允许您保持所有数据以及与具有此实体的实体相关的功能。此数据的可见性级别是一个相关但不完全相同的概念。例如。 Employee对象使用它来篡改所有员工数据和功能(方法)。请注意,这不是强制执行,而是通过OO语言启用

如果你出生在OO时代,这对你来说听起来很自然,但这是从功能编程到OOP的强大的重大飞跃,包括概念(设计)和支持这种范式的语言。

引自维基百科article

  

用编程语言编写   封装用于指代一个   两个相关但不同的概念,   有时甚至是组合   物:

     
      
  • 一种限制访问某些内容的语言机制   对象的组件。
  •   
  • 一种便于数据捆绑的语言结构   方法(或其他功能)   对该数据进行操作。
  •   

答案 6 :(得分:0)

说我像这样使用你的代码:

Employee employee = new Employee();
int age = employee.getAge();
// Do something with age

在这里,除非我查看您的源代码,否则我完全不知道Employee如何计算其年龄。据我所知,getAge()看起来像这样:

public int getAge() {
    return new java.util.Random().nextInt( 100 );
}

或者更复杂的东西。我只是不知道。

所以在你的第二个例子中,getAge()只返回私有成员变量的事实对我来说是完全隐藏的。