面向对象的特点我们都熟知是封装,继承和多态。但是其实在今天之前的我也并没有对这些概念有深入了解。
如果问你什么是封装,可能有人会说是将变量私有化,然后对外提供接口。但是为什么要这么做呢,将类private不如public来的便捷,直接访问person.name多么容易,为何还要使用get方法和set方法呢。
我们可以先举一个不使用封装的例子:
public class Man{
public String name;
public Women wife;
public double money;
public void marry(Woman woman){
this.wife = woman;
woman.marry(this);
}
}
public class Woman{
public String name;
public Man husband;
public void maryy(Man man){
this.husband = man;
}
}
代码看起来很精简,写个测试方法试一下:
@Test
public void testPackage(){
Man man = new Man();
man.name = "jack";
man.money = 1000000;
Woman woman = new Woman();
woman.name = "lucy";
man.marry(woman);
System.out.print(man.name+"and"+man.wife.name);
System.out.print(man.name+"and"+man.money;
//输出 jack and lucy
//jack and 1000000
}
看起来测试代码也完美,这时候来了一个小偷
public class Thief{
private double stealMoney = 0;
private List<Women> womens = new ArrayList<>();
public void stealMoney(Man man){
stealMoney += man.money/100;
man.money = 990000;
System.out.print("偷了钱");
}
}
public void testPackage1(){
Man man = new Man();
man.name = "jack";
man.money = 1000000;
Woman woman = new Woman();
woman.name = "lucy";
man.marry(woman);
Thief thief = new Thief();
thief.stealMoney(man);
System.out.print(man.name+"and"+man.money;
//jack and 990000
}
我们看到,man的钱被偷走了10000,那这个时候我们就要想办法解决这个问题了。
封装就是可以解决这个问题的一个好办法。
封装
//首先为man对象做封装
public class PackageMan{
private String name;//私有化名字
private PackageWoman wife;//必须私有
private double money;//通通私有
//先写一个构造函数,为了方便
public PackageMan(String name,double money){
this.name = name;
this.money = money;
}
//结婚
public void marry(PackageWoman woman){
this.wife = woman;
woman.marry(this);
}
//各种getter和setter
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public PackageWoman getWife() {
return wife;
}
public double getMoney() {
return money;
}
}
//PackageWoman
public class PackageWoman {
private String name;
private PackageMan husband;
public void marry(PackageMan man){
this.husband = man;
}
public PackageWoman(String name) {
this.name = name;
}
public String getName() {
return name;
}
public PackageMan getHusband() {
return husband;
}
public void setName(String name) {
this.name = name;
}
}
看起来复杂了很多,但是真的有用吗?
赶紧加个thief测试一下,什么?小偷已经在路上拦截了?
原来是因为我们压根就没有对外提供setMoney的方法。
他可以获取你有多少钱,但是他却没法进行操作。
但是防止了小偷的操作,如果自己想操作呢,提供set方法又会让所有人都能改。。。
稍等,如果提供set方法,是真的所有人都能改,吗?
我们再来看看
public void setMoney(PackageMan man,double money){
if(man == this){
this.money = money;
}else {
System.out.println("喂,110吗?"+man.getName()+"抢钱!");
}
}
这样呢?只有你自己可以修改,别人都不可以,测试一下:
public void testPackage1(){
PackageMan man = new Man();
PackageMan man1 = new Man();
man.setMoney(man,2000000);
man.setMoney(man1,2000000);
System.out.print(man.name+"and"+man.money;
//jack and 990000
}
但是你老婆不满意了,凭什么只有你自己能改?我也想改!
这种要求,还是应该满足一下的,怎么做呢?
public void setMoney(Object o,double money) {
if (o == this || o == this.wife) {
this.money = money;
} else {
System.out.println("喂,110吗?有人抢钱!");
}
}
我相信看到这里你一定和我有一样的疑惑,传进来的是Object我要怎么得知来骚扰我金钱的人是谁呢?
这里可以再写点代码判断一下传进来的数据类型,强转类型后再调用相应的方法。(还有其他方法后面说)
除此之外还有个更大的疑惑,加了set方法以后小偷还是可以偷你的钱啊,小偷可以通过你自己这个对象调用方法来改变你自己不就行了。
那么怎样才能让小偷即使得到”你自己这个对象“还无论如何都不能改变你的属性值呢。
这个以后再详细讲吧。
总结
封装不仅仅是private + getter和setter,使用封装可以对setter做更深层次的定制。
可以规定执行setter方法的对象,也可以对数据做要求,还可以做类型转换等等一系列事情。
使用封装不仅安全,而且可以简化操作。
网友评论