面向對象的特點我們都熟知是封裝,繼承和多態(tài)。但是其實在今天之前的我也并沒有對這些概念有深入了解。
如果問你什么是封裝,可能有人會說是將變量私有化,然后對外提供接口。但是為什么要這么做呢,將類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;//通通私有
//先寫一個構造函數(shù),為了方便
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我要怎么得知來騷擾我金錢的人是誰呢?
這里可以再寫點代碼判斷一下傳進來的數(shù)據(jù)類型,強轉類型后再調用相應的方法。(還有其他方法后面說)
除此之外還有個更大的疑惑,加了set方法以后小偷還是可以偷你的錢啊,小偷可以通過你自己這個對象調用方法來改變你自己不就行了。
那么怎樣才能讓小偷即使得到”你自己這個對象“還無論如何都不能改變你的屬性值呢。
這個以后再詳細講吧。
總結
封裝不僅僅是private + getter和setter,使用封裝可以對setter做更深層次的定制。
可以規(guī)定執(zhí)行setter方法的對象,也可以對數(shù)據(jù)做要求,還可以做類型轉換等等一系列事情。
使用封裝不僅安全,而且可以簡化操作。