这个问题已经在这里有一个答案:
- 为什么要使用getter和setter /存取? [关闭] 38个答案
我们总是说,数据将被封装,如果我们简单地定义变量, private
和定义的getter setter方法来访问这些变量。 我的问题是,如果我们可以通过getter和setter访问的变量(数据)虽然,数据是怎么来隐藏或安全的呢?
我GOOGLE了很多关于解释,但一无所获。 只是在他们的博客和帖子,这是一个数据隐藏技术,但并没有解释/说过的每一个阐述它。
期待获得适当的,满意的,在计算器的论坛在这里解释。
我明白你的问题的方式是,虽然我们变量声明为private
,因为这些变量可以使用getter和setter访问时,不是私人的。 因此,什么是这样做的意义何在?
那么,使用getter和setter时,你可以限制访问private
变量。
即
private int x;
public int getInt(String password){
if(password.equals("RealPassword")){
return x;
}
}
而同为setter方法。 希望这可以帮助!
封装不仅仅是定义访问和mutator方法一类多。 它是由在最小化类之间的相互依赖性的面向对象编程的更广泛的概念,它是通过信息隐藏通常被实现。
封装的好处是改变的事情,而不影响其用户的能力 。
在面向对象的编程语言如Java,您可以通过使用访问修饰符(公共的,受保护的,私人的,不加修饰,这意味着包私人)隐藏实现细节封装。 与这些级别的可访问的,则控制封装的水平,较少限制的水平,更昂贵的变化是当它发生和多个耦合的类是与其他从属类(即,用户类型,亚类)。
因此, 我们的目标是不是隐藏数据本身 ,而是这个数据是如何操作的实施细则。
我们的想法是,通过提供你访问这个数据的公共接口。 以后,您可以更改数据的内部表示不影响类的公共接口。 相反,通过公开数据本身,你妥协封装,因此,改变你处理数据的方式,而不会影响其用户的能力。 创建数据本身的依赖,而不是与类的公共接口。 你会麻烦要创建一个完美的鸡尾酒时,“变”终于找到你了。
有几个原因,您可能要封装到您的域的访问。 约书亚布洛赫在他的书有效的Java,在项目14:尽量减少类和成员的可访问性,提到了几个令人信服的理由,这是我在这里引用:
- 您可以限制可以存储在一个字段(即性别必须是F或M)的值。
- 当字段被修改(触发事件,验证等),你可以采取行动。
- 您可以通过同步方法提供线程安全。
- 可以切换到一个新的数据表示(即计算字段,不同的数据类型)
然而,封装是不是隐藏字段的更多。 在Java中,你可以隐藏全部课程,通过这个,隐藏整个API的实现细节。 认为,例如,在该方法中Arrays.asList()
它返回一个List
实现,但你不关心是什么实现,只要它满足List
界面,对不对? 实施可以在未来,而不会影响该方法的用户更改。
封装之美
现在,在我看来,要真正理解封装,首先必须了解抽象。
想想,例如,在抽象的概念车的水平。 汽车是在其内部实现复杂。 他们有几个子系统,如传动系统,制动系统,燃料系统等。
然而,我们已经简化了抽象,我们通过他们的抽象的公共接口与世界上所有的汽车互动。 我们知道,所有的汽车有一个方向盘,通过它我们控制方向,他们有,当你按下它,你加速的汽车,控制速度,另外一个,当你按下它,你让它停下踏板,和你有一个齿轮棒,让你去向前或向后你控制。 这些特点构成了汽车抽象的公共接口。 早晨,您可以驾驶的轿车,然后把它弄出来,并驱动SUV下午,就好像是同样的事情。
然而,我们很少知道如何将所有这些功能都在引擎盖下实现的细节。 想的时候,汽车没有一个液压定向系统。 有一天,汽车制造商发明了它,他们决定它把它放在汽车从那里。 不过,这并没有改变哪些用户进行互动的方式。 至多,有经验的用户在使用定向系统的改进。 因为汽车的内部实现封装像这样的改变是可能的。 变化可以在不影响其公共接口可以安全地完成。
现在,认为汽车制造商决定把以下的车油箱盖,而不是在其一个侧面。 你去购买这些新车型之一,当你用完了气体的你去加油站,你没有找到油箱盖。 突然你意识到这是以下的车,但你不能与气体泵软管达到它。 现在,我们已经打破了公共接口的合同,因此,整个世界破裂,它分崩离析,因为事情没有工作,预计的方式。 像这样的改变将花费数百万美元。 我们需要改变这一切气泵世界。 当我们破坏了封装,我们必须付出一定的代价。
所以,你可以看到,封装的目标是尽量减少相互依存和促进变革。 您可以通过最小化的实现细节曝光最大化封装。 一类的状态,只应通过公共接口来访问。
我真的建议你读报纸艾伦·斯奈德称为封装和继承在面向对象的编程语言 。 该链接指向上ACM原纸,但我敢肯定,你将能够通过谷歌找到一个PDF副本。
该数据是安全的,因为你可以在你的getter / setter做额外的逻辑,它不可能改变你的变量的值。 试想一下,你的代码没有用空变量工作,所以在你的二传手,你可以核对空值,并指定一个默认值,该值!= NULL。 所以你的代码仍然在工作,不管是否有人试图为你的变量空。
我的问题是,如果我们可以通过getter和setter访问的变量(数据)虽然,数据是怎么来隐藏或安全的呢?
您可以封装在例如getter / setter方法的逻辑
public void setAge(int age){
if(age < 0){
this.age = 0;
}else{
this.age = age;
}
}
在通过getter和setter领域的普通封装叶更改更大的灵活性。
如果字段直接访问你被卡住“笨田”。 字段只能写入和读取。 没有什么可以同时访问现场进行。
当使用方法,你可以做任何你想要在设置/读取值。 随着马库斯和Jigar提到的验证。 此外,你可以决定某一天,该值从另一个值导出或某些行为必须当值的变化来执行。
怎么来的数据被隐藏或安全
数据既不是隐藏的,也不安全使用getter和setter方法。 它只是给你做它的安全的可能性。 什么是隐藏的是执行,而不是数据。
数据验证是主要回答你关于是否有游戏存取及/或存取器封装如何提供安全性的问题。 也有人提到这个使用具有故障安全设置在突变的默认值的例子。 你回答说,你喜欢抛出异常,而不是,这是伟大的,但识别你有不良数据,当你去使用它不会改变你有不良数据的事实 。 难道因此不是最好的捕捉异常数据被修改之前 ,即做的突变? 通过这种方式,实际的数据绝不会被修改,除非突变已经验证了它作为是有效的,因此原始数据在坏数据的情况下保存。
我还只是一个学生自己,但我有完全相同的,虽然你当我第一次遇到的封装,所以我花了一些时间计算出来。
考虑到线程时,我喜欢这个解释。 如果你做了公共领域是怎么您的实例会知道当某个线程改变了它的领域之一? 做到这一点的唯一方法是用封装,或者更简单的放给getter和setter那场,因此你总是知道,可以检查/反应领域的更新通知。
封装使得代码更容易被其他人重用。 使用封装的另一个重要原因是,接口不能声明字段,但他们可以申报方法,它可以指一个领域!
方法正确地与在开始一个动词命名。 如:的getName(),的setName(),isDying()。 它可以帮助阅读代码!