•通过代码深入了解
首先我们先来看两个类:Husband.java、Wife.java;
HusBand.jaba:
public classHusband {/** 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性*/
privateString name ;privateString sex ;private intage ;privateWife wife;/** setter()、getter()是该对象对外开发的接口*/
public voidsetName(String name) {this.name =name;
}public voidsetSex(String sex) {this.sex =sex;
}public void setAge(intage) {this.age =age;
}public voidsetWife(Wife wife) {this.wife =wife;
}publicString getName() {returnname;
}publicString getSex() {returnsex;
}public intgetAge() {returnage;
}
}
Wife.java:
public classWife {privateString name;private intage;privateString sex;privateHusband husband;public voidsetName(String name) {this.name =name;
}public void setAge(intage) {this.age =age;
}public voidsetSex(String sex) {this.sex =sex;
}public voidsetHusband(Husband husband) {this.husband =husband;
}publicString getName() {returnname;
}publicString getSex() {returnsex;
}publicHusband getHusband() {returnhusband;
}
}
从上面两个实例我们可以看出 Husband 类里 wife 引用是没有 getter() 的,同时 Wife 的 age 也是没有 getter() 方法的。
至于理由我想各位都懂的,男人嘛深屋藏娇妻嘛,没有那个女人愿意别人知道她的年龄。
所以封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法;
如果不想被外界访问,我们大可不必提供方法给外界访问。
但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
比如我们将一个房子看做是一个对象,里面的漂亮的装饰,如沙发、电视剧、空调、茶桌等等都是该房子的私有属性;
但是如果我们没有那些墙遮挡,是不是别人就会一览无余呢?
没有一点儿隐私!
就是存在那个遮挡的墙,我们既能够有自己的隐私而且我们可以随意的更改里面的摆设而不会影响到其他的。
但是如果没有门窗,一个包裹的严严实实的黑盒子,又有什么存在的意义呢?
所以通过门窗别人也能够看到里面的风景。
所以说门窗就是房子对象留给外界访问的接口。
通过这个我们还不能真正体会封装的好处,现在我们从程序的角度来分析封装带来的好处;
如果我们不使用封装,那么该对象就没有 setter() 和 getter(),
那么Husband类应该这样写:
public classHusband {publicString name ;publicString sex ;public intage ;publicWife wife;
}
我们应该这样来使用它:
Husband husband = newHusband();
husband.age= 30;
husband.name= "张三";
husband.sex= "男"; //貌似有点儿多余
但是哪天如果我们需要修改Husband,例如将 age 修改为 String 类型的呢?
你只有一处使用了这个类还好,如果你有几十个甚至上百个这样地方,你是不是要改到崩溃。
如果使用了封装,只需要稍微改变下 Husband类 的 setAge() 方法即可:
public classHusband {/** 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性*/
privateString name ;privateString sex ;private String age ; /*改成 String类型的*/
privateWife wife;public void setAge(intage) {//转换即可
this.age =String.valueOf(age);
}publicString getAge() {returnage;
}/**省略其他属性的setter、getter **/}
其他的地方依然那样引用 (husband.setAge(22)) 保持不变。
到了这里我们确实可以看出,封装确实可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码。
我们在看这个好处:可以对成员变量进行更精确的控制。
还是那个Husband,一般来说我们在引用这个对象的时候是不容易出错的,但是有时你迷糊了,写成了这样:
Husband husband = newHusband();
husband.age= 300;
也许你是因为粗心写成了,你发现了还好,如果没有发现那就麻烦大了,毕竟谁见过300岁的老妖怪啊!
但是使用封装我们就可以避免这个问题,我们对 age 的访问入口做一些控制,如:
public classHusband {/** 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性*/
privateString name ;privateString sex ;private int age ; /*改成 String类型的*/
privateWife wife;public void setAge(intage) {if(age > 120){
System.out.println("ERROR:error age input...."); //提示错误信息
}else{this.age =age;
}
}public intgetAge() {returnage;
}/**省略其他属性的setter、getter **/}
上面都是对setter方法的控制,其实通过使用封装我们也能够对对象的出口做出很好的控制。
例如性别我们在数据库中一般都是已 0、1 方式来存储的;
但是在前台我们又不能展示 0、1,这里我们只需要在 getter() 方法里面做一些转换即可。
publicString getSexName() {if(sex.equals("0")){
sexName= "女";
}else if(sex.equals("1")){
sexName= "男";
}else{
sexName= "人妖???";
}returnsexName;
}
在使用的时候我们只需要使用 sexName 即可实现正确的性别显示。
同理也可以用于针对不同的状态做出不同的操作。