评论类型
封装,真的吗?
我已经写过关于封装的文章,但是如果木头很硬,我想敲几次钉子是很自然的。
年轻的时候,当我学习OOP时 ,就被告知了它的特点:
- 遗产
- 多态性
- 封装形式
这是在维基百科上找到的定义 :
封装用于指两个相关但截然不同的概念之一,有时还指其组合:
- 一种语言机制,用于限制直接访问对象的某些组件。
- 一种语言构造,它有助于将数据与对数据进行操作的方法(或其他功能)捆绑在一起。
简而言之,封装意味着不能直接访问对象的状态,而只能通过其方法。 在Java中,它直接转换为具有私有属性和公共访问器(即getter和setter)的JavaBeans约定 。 这是当前困扰我们的悲伤状态,许多人在谈论封装时都提到了这种状态。
对于这种模式根本没有封装! 不相信我吗? 检查以下代码段:
publicclassPerson{
privateDatebirthdate=newDate();
publicDategetBirthdate(){
returnbirthdate;
}
}
鉴于没有设置方法,因此不可能在Person
实例中更改日期。 但它是:
Personperson=newPerson();
Datedate=person.getBirthdate();
date.setTime(0L);
哎哟! 毕竟,国家没有那么好被封装...
一切都归结为一个很小的区别:我们希望访问生日的值,但我们很高兴将引用返回到保存该值的birthdate
字段。 让我们对其进行更改,以将值本身与引用分开:
publicclassPerson{
privateDatebirthdate=newDate();
publicDategetBirthdate(){
returnnewDate(birthdate.getTime());
}
}
通过创建一个与原始引用不共享任何内容的新Date
实例,可以实现真正的封装。 现在可以安全地调用getBirthdate()
。
请注意,本质上是不可变的类 -在Java中,原语, String
以及像这样开发的类,完全可以安全共享。 因此,完全public
那些类型的字段而忽略吸气剂是完全可以接受的。
还要注意, 例如在构造函数中注入引用会带来完全相同的问题,应以相同的方式进行处理。
publicclassPerson{
privateDatebirthdate;
publicPerson(Datebirthdate){
this.birthdate=newDate(birthdate.getTime());
}
publicDategetBirthdate(){
returnnewDate(birthdate.getTime());
}
}
问题是,大多数虔诚地调用封装的人都乐于与外界分享他们的领域参考。
结论
这里有两个结论:
- 如果您具有可变字段,则简单的getter(例如由IDE生成的那些)将不提供封装。
- 只有返回可变字段,而不返回字段本身,才能使用可变字段实现真正的封装。
- 一旦有了不可变的字段,就可以通过getter访问它们或让字段
final
完全相同。
注意:如果您了解上述模因参考,则对您表示敬意 。
翻译自: https://blog.frankel.ch/encapsulation-dont-think-means-think-means/