数据隐藏的含义是什么?

OOP最重要的一个方面是数据隐藏。 有人可以使用一段简单的代码解释数据隐藏的确切原因以及我们需要它的原因吗?

数据或信息隐藏是 David Paranas提出的设计原则

它表示你应该在程序的一个部分中隐藏设计决策,这些部分可能会从程序的其他部分发生变化,从而保护其他部分不受第一部分变化的影响。

封装是编程语言function,可以实现数据隐藏 。 但请注意,即使没有封装,您也可以隐藏数据\信息。 例如,使用非面向对象编程语言中的模块或函数。 因此,封装不是数据隐藏,而只是实现它的手段

在进行封装时,如果忽略底层主体,那么你将没有一个好的设计。 例如,考虑这个类 –

public class ActionHistory { private string[] _actionHistory; public string[] HistoryItems { get{return _actionHistory; } set{ _actionHistory = value; } } } 

这个调用封装了一个数组。 但它并没有隐藏使用string []作为内部存储的设计决策。 如果我们想稍后更改内部存储,它也会影响使用此类的代码。

更好的设计是 –

 public class ActionHistory { private string[] _actionHistory; public IEnumerable HistoryItems { get{return _actionHistory; } } } 

我猜测数据隐藏你的意思是封装或在对象中有一个变量,只有通过get和modify方法公开它,通常当你想强制设置一个值的某些逻辑时?

 public class Customer { private decimal _accountBalance; public decimal GetBalance() { return _accountBalance; } public void AddCharge(decimal charge) { _accountBalance += charge; if (_accountBalance < 0) { throw new ArgumentException( "The charge cannot put the customer in credit"); } } } 

即在这个例子中,我允许消费类获得Customer的平衡,但我不允许他们直接设置它。 但是,我已经公开了一种方法,允许我通过在AddCharge方法中通过AddCharge添加来修改类实例中的AddCharge

这是一篇你可能会觉得有用的文章 。

信息隐藏(或更准确地说是封装)是限制直接访问您的类信息的做法。 我们在C#中使用getter / setter或更高级的构造称为属性。

这使我们可以管理数据的访问方式,因此我们可以在以后需要时对输入进行清理并格式化输出。

这个想法是在任何公共界面上,我们不能相信调用主体做正确的事情,所以如果你确定它只能做正确的事情,你就会遇到更少的问题。

例:

 public class InformationHiding { private string _name; public string Name { get { return _name; } set { _name = value; } } /// This example ensures you can't have a negative age /// as this would probably mess up logic somewhere in /// this class. private int _age; public int Age { get { return _age; } set { if (value < 0) { _age = 0; } else { _age = value; } } } } 

想象一下,你class级的用户正试图想出让你的class级不再履行合同的方法。 例如,您的Banking对象可能有一个合同,确保所有交易都记录在日志中。 假设银行的TransactionLog的变异是公开可访问的; 现在,消费类可以启动可疑事务并修改日志以删除记录。

这是一个极端的例子,但基本原则保持不变。 由class级作者维护class级的合同义务,这意味着你要么必须履行弱合同义务(减少class级的有用性),要么你需要非常小心你的州如何变异。

什么是数据隐藏?

这是一个例子:

 public class Vehicle { private bool isEngineStarted; private void StartEngine() { // Code here. this.isEngineStarted = true; } public void GoToLocation(Location location) { if (!this.isEngineStarted) { this.StartEngine(); } // Code here: move to a new location. } } 

如您所见, isEngineStarted字段是私有的,即。 从class级本身可以访问。 实际上,当调用Vehicle类型的对象时,我们确实需要将车辆移动到某个位置,但不需要知道如何完成。 例如,对于调用者对象,如果引擎启动与否则无关紧要:如果不是,则在移动到某个位置之前,由Vehicle对象启动它。

我们为什么需要这个?

主要是为了使代码更易于阅读和使用。 类可能有几十个或几百个仅由它们使用的字段和属性。 将所有这些领域和财产暴露给外部世界将是令人困惑的。

另一个原因是控制私有字段/属性的状态更容易。 例如,在上面的示例代码中,假设StartEngine正在执行某些任务,然后为this.isEngineStarted分配true 。 如果isEngineStarted是public,则另一个类可以将其设置为true ,而不执行StartEngine任务。 在这种情况下, isEngineStarted的值将不可靠。

通过数据隐藏,您可能是指封装。 封装由维基百科定义如下:

封装从发送消息的对象隐藏类的function细节。

为了进一步解释,在设计课程时,您可以设计公共和私人成员。 该类将其公共成员公开给程序中的其他代码,但只有类中编写的代码才能访问私有成员。

通过这种方式,类可以公开公共接口,但可以隐藏该接口的实现,这可以包括隐藏类所持有的数据的实现方式。

下面是一个简单的数学角度类的示例,它暴露了度和弧度的值,但数据的实际存储格式是隐藏的,并且可以在将来更改而不会破坏程序的其余部分。

 public class Angle { private double _angleInDegrees; public double Degrees { get { return _angleInDegrees; } set { _angleInDegrees = value; } } public double Radians { get { return _angleInDegrees * PI / 180; } set { _angleInDegrees = value * 180 / PI; } } } 

数据隐藏定义为通过将新类方法命名为与基类​​方法相同的名称来隐藏派生类中的基类方法。

 class Person { public string AnswerGreeting() { return "Hi, I'm doing well. And you?"; } } class Employee : Person { new public string AnswerGreeting() { "Hi, and welcome to our resort."; } } 

在此c#代码中, new关键字阻止编译器发出警告,指出AnswerGreeting的基类实现被派生类中具有相同名称的方法的实现隐藏。 也称为“通过inheritance隐藏数据”。