知識點總結之-面向對象封裝

第9天 面向對象
今日內容介紹
 面向對象
 封裝
第1章 面向對象
1.1 理解什麼是面向過程、面向對象
面向過程與面向對象都是我們編程中,編寫程序的一種思維方式。
 面向過程的程序設計方式,是遇到一件事時,思考“我該怎麼做”,然後一步步實現的過程。
例如:公司打掃衛生(擦玻璃、掃地、拖地、倒垃圾等),按照面向過程的程序設計方式會思考“打掃衛生我該怎麼做,然後一件件的完成”,最後把公司衛生打掃乾淨了。
 面向對象的程序設計方式,是遇到一件事時,思考“我該讓誰來做”,然後那個“誰”就是對象,他要怎麼做這件事是他自己的事,反正最後一羣對象合力能把事就好就行了。
例如,公司打掃衛生(擦玻璃、掃地、拖地、倒垃圾等),按照面向對象的程序設計方式會思考“我該讓誰來做,如小明擦玻璃、讓小麗掃地、讓小郭拖地、讓小強倒垃圾等”,這裏的“小明、小麗、小郭、小強”就是對象,他們要打掃衛生,怎麼打掃是他們自己的事,反正最後一羣對象合力把公司衛生打掃乾淨了。
1.2 面向對象舉例
 買電腦(組裝機)
先使用面向過程說明買電腦這件事:假如我們需要買組裝電腦,這時首先會在網上查詢具體每一個硬件的參數和報價。然後會去電腦城進行多家詢價,接着詢價結束後回家根據具體的結果分析出自己比較滿意的哪家報價,接着會到這家店裏進行組裝,組裝時還需要進行現場監督,組裝完成安裝相應的系統,然後電腦抱回家。
分析上述整個過程大體分一下幾步:上網查詢參數和報價、電腦城詢價、現場安裝和監督、抱電腦回家。在整個過程中我們參與了每一個細節,並且會感覺相當累。
使用面向對象說明買電腦這件事:假如我們需要買組裝機,這時應該找一個懂電腦硬件的人,讓他幫我們查看參數和報價,並進行詢價和殺價,以及現場組裝監督。而我們自己並不需要親歷親爲具體怎麼做,只要告訴這個人我們想要的具體需求即可。
分析上述整個過程,發現瞬間變的十分輕鬆,只要找到懂電腦硬件的這個人,我們的問題都可以解決。並且在這個過程中我們不用那麼辛苦。
1.3 面向對象思維方式的好處
通過生活中的真實場景使用面向對象分析完之後,我們開始分析面向過程和麪向對象的差異做出總結:
 面向對象思維方式是一種更符合人們思考習慣的思想
 面向過程思維方式中更多的體現的是執行者(自己做事情),面向對象中更多的體現是指揮者(指揮對象做事情)。
 面向對象思維方式將複雜的問題簡單化。
第2章 類與對象
2.1 對象在需求中的使用
對面向對象有了瞭解之後,我們來說說在具體問題中如何使用面向對象去分析問題,和如何使用面向對象。
我們把大象裝冰箱爲例進行分析。
在針對具體的需求,可以使用名詞提煉的辦法進行分析,尋找具體的對象。
需求:把大象裝冰箱裏
對象:大象、冰箱
分三步:
1、打開冰箱門
2、將大象裝進去
3、關閉冰箱門
分析發現打開、裝、關閉都是冰箱的功能。即冰箱對象具備如下功能:
冰箱打開
冰箱存儲
冰箱關閉
用僞代碼描述,上述需求中有兩個具體的事物 大象 和 冰箱
描述大象:
class 大象
{
}
描述冰箱
class冰箱
{
void 打開(){}
void 存儲(大象){}
void 關閉(){}
}
當把具體的事物描述清楚之後,需要使用這些具體的事物,Java使用具體的事物,需要通過new關鍵字來創建這個事物的具體實例。
使用對象:
1、創建冰箱的對象
冰箱 bx = new 冰箱();
2、調用冰箱的功能
對象.功能();
bx.打開();
bx.存儲(new 大象());
bx.關閉();
 總結:
1、先按照名詞提煉問題領域中的對象
2、對對象進行描述,其實就是在明確對象中應該具備的屬性和功能
3、通過new的方式就可以創建該事物的具體對象
4、通過該對象調用它以後的功能。
2.2 對象在代碼中的體現
在分析現實生活中的事物時發現,這些事物都有其具體的特點和功能,這些特點和功能就組成了這個特殊的事物。
描述小汽車。
分析:
事物的特點(屬性):
顏色。
輪胎個數。
事物的(功能):
運行。

發現:事物其實就是由特點(屬性)和行爲(功能)組成的。
可以簡單理解:屬性就是數值,其實就是變量;行爲就是功能,就是方法。
小汽車 {
顏色;
輪胎個數;
運行() { }
}
通過計算機語言Java來描述這個事物。
 定義類的格式
public class 類名 {
//可編寫0至n個屬性
數據類型 變量名1;
數據類型 變量名2;

//可編寫0至n個方法
修飾符 返回值類型 方法名(參數){
	執行語句;

}
}
 汽車類
public class Car {
String color;
int number;

void run() {
	System.out.println(color + ":" + number);
}

}
通過代碼的描述,知道類的真正意義就是在描述事物。屬性和功能統稱爲事物中的成員。
事物的成員分爲兩種:成員屬性和成員功能。
成員屬性在代碼中的體現就是成員變量
成員功能在代碼中的體現就是成員方法
把寫好的代碼測試一下。需要一個可以獨立運行類。
 創建對象的格式:
類名 對象名 = new 類名();
 測試類
public class CarDemo {
public static void main(String[] args) {
/*
* 測試:Car類中的run方法。
*/
// 1,創建Car的對象。給對象起個名字。
Car c = new Car();// c是類類型的變量。c指向了一個具體的Car類型的對象。
// 2,通過已有的對象調用該對象的功能。格式:對象.對象成員;
// 3,可以該對象的屬性賦值。
c.color = “red”;
c.number = 4;
c.run();
}
}
2.3 對象的內存圖解
經過上面對小汽車的描述,和Java代碼測試,我們雖然可以將生活中的事物使用Java代碼描述出來,但是這些代碼在內存中是如何執行的,接下來我們需要研究下對象在內存的圖解。
接下來就是分析對象在內存中的分配情況。這裏需要畫圖一步一步演示,嚴格按照畫圖流程講解內存對象創建過程。

2.4 類和對象的區別
面向對象的編程思想力圖在程序中對事物的描述與該事物在現實中的形態保持一致。爲了做到這一點,面向對象的思想中提出兩個概念,即類和對象。其中,類是對某一類事物的抽象描述,而對象用於表示現實中該類事物的個體。接下來通過一個圖例來抽象描述類與對象的關係,如下圖所示。

圖1-1 類與對象
在上圖中,可以將玩具模型看作是一個類,將一個個玩具看作對象,從玩具模型和玩具之間的關係便可以看出類與對象之間的關係。類用於描述多個對象的共同特徵,它是對象的模板。對象用於描述現實中的個體,它是類的實例。從上圖中可以明顯看出對象是根據類創建的,並且一個類可以對應多個對象,接下來分別講解什麼是類和對象。
經過前面幾個知識點的學習,基本上掌握了類是用於描述事物的,類中可以定義事物的屬性和行爲。而對象是通過描述的這個類,使用new關鍵字創建出來,通過對象就可以調用該對象具體的屬性和功能了。
2.5 局部變量和成員變量區別
理解清楚了類和對象之後,結合前5天的學習知識,發現在描述類的屬性和前面學習定義變量差別不大,唯一區別就是位置發生了改變,那麼類中定義的變量,和在方法定義的變量有啥差別呢?
回憶以前學習時變量的定義方式,和位置,以及現在定義類中屬性的特點。總結下面幾點異同
區別一:定義的位置不同
定義在類中的變量是成員變量
定義在方法中或者{}語句裏面的變量是局部變量
區別二:在內存中的位置不同
成員變量存儲在對內存的對象中
局部變量存儲在棧內存的方法中
區別三:聲明週期不同
成員變量隨着對象的出現而出現在堆中,隨着對象的消失而從堆中消失
局部變量隨着方法的運行而出現在棧中,隨着方法的彈棧而消失
區別四:初始化不同
成員變量因爲在堆內存中,所有默認的初始化值
局部變量沒有默認的初始化值,必須手動的給其賦值纔可以使用。
2.6 基本類型和引用類型作爲參數傳遞
引用類型數據和基本類型數據作爲參數傳遞有沒有差別呢?我們用如下代碼進行說明,並配合圖解讓大家更加清晰
class Demo
{
public static void main(String[] args)
{
int x = 4;
show(x);
System.out.println(“x=”+x);
}
public static void show(int x)
{
x = 5;

}

}
基本類型作爲參數傳遞時,其實就是將基本類型變量x空間中的值複製了一份傳遞給調用的方法show(),當在show()方法中x接受到了複製的值,再在show()方法中對x變量進行操作,這時只會影響到show中的x。當show方法執行完成,彈棧後,程序又回到main方法執行,main方法中的x值還是原來的值。
class Demo
{
int x ;
public static void main(String[] args)
{

	Demo d = new Demo();
	d.x = 5;
	show(d);
	System.out.println("x="+d.x);
}
public static void show(Demo d)
{
	d.x = 6;
}

}
當引用變量作爲參數傳遞時,這時其實是將引用變量空間中的內存地址(引用)複製了一份傳遞給了show方法的d引用變量。這時會有兩個引用同時指向堆中的同一個對象。當執行show方法中的d.x=6時,會根據d所持有的引用找到堆中的對象,並將其x屬性的值改爲6.show方法彈棧。
由於是兩個引用指向同一個對象,不管是哪一個引用改變了引用的所指向的對象的中的值,其他引用再次使用都是改變後的值。

第3章 封裝
3.1 封裝概述
提起封裝,大家並不陌生。前面我們學習方法時,就提起過,將具體功能封裝到方法中,學習對象時,也提過將方法封裝在類中,其實這些都是封裝。
封裝,它也是面向對象思想的特徵之一。面向對象共有三個特徵:封裝,繼承,多態。接下來我們具體學習封裝。
 封裝表現:
 1、方法就是一個最基本封裝體。
 2、類其實也是一個封裝體。
 從以上兩點得出結論,封裝的好處:
 1、提高了代碼的複用性。
 2、隱藏了實現細節,還要對外提供可以訪問的方式。便於調用者的使用。這是核心之一,也可以理解爲就是封裝的概念。
 3、提高了安全性。

3.2 封裝舉例
機箱:
一臺電腦,它是由CPU、主板、顯卡、內存、硬盤、電源等部件組長,其實我們將這些部件組裝在一起就可以使用電腦了,但是發現這些部件都散落在外面,很容造成不安全因素,於是,使用機箱殼子,把這些部件都裝在裏面,並在機箱殼上留下一些插口等,若不留插口,大家想想會是什麼情況。
總結:機箱其實就是隱藏了辦卡設備的細節,對外提供了插口以及開關等訪問內部細節的方式。
3.3 私有private
瞭解到封裝在生活的體現之後,又要回到Java中,細說封裝的在Java代碼中的體現,先從描述Person說起。
描述人。Person
屬性:年齡。
行爲:說話:說出自己的年齡。
class Person {
int age;
String name;

public void show() {
	System.out.println("age=" + age + ",name" + name);
}

}

public class PersonDemo {
public static void main(String[] args) {
// 創建Person對象
Person p = new Person();
p.age = -20; // 給Person對象賦值
p.name = “人妖”;
p.show(); // 調用Person的show方法
}
}
通過上述代碼發現,雖然我們用Java代碼把Person描述清楚了,但有個嚴重的問題,就是Person中的屬性的行爲可以任意訪問和使用。這明顯不符合實際需求。
可是怎麼才能不讓訪問呢?需要使用一個Java中的關鍵字也是一個修飾符 private(私有,權限修飾符)。只要將Person的屬性和行爲私有起來,這樣就無法直接訪問。
class Person {
private int age;
private String name;

public void show() {
	System.out.println("age=" + age + ",name" + name);
}

}
年齡已被私有,錯誤的值無法賦值,可是正確的值也賦值不了,這樣還是不行,那腫麼辦呢?按照之前所學習的封裝的原理,隱藏後,還需要提供訪問方式。只要對外提供可以訪問的方法,讓其他程序訪問這些方法。同時在方法中可以對數據進行驗證。
一般對成員屬性的訪問動作:賦值(設置 set),取值(獲取 get),因此對私有的變量訪問的方式可以提供對應的 setXxx或者getXxx的方法。
class Person {
// 私有成員變量
private int age;
private String name;

// 對外提供設置成員變量的方法
public void setAge(int a) {
	// 由於是設置成員變量的值,這裏可以加入數據的驗證
	if (a < 0 || a > 130) {
		System.out.println(a + "不符合年齡的數據範圍");
		return;
	}
	age = a; 
}

// 對外提供訪問成員變量的方法
public void getAge() {
	return age;
}

}
 總結:
類中不需要對外提供的內容都私有化,包括屬性和方法。
以後再描述事物,屬性都私有化,並提供setXxx getXxx方法對其進行訪問。
 注意:私有僅僅是封裝的體現形式而已。
3.4 this關鍵字
3.4.1 成員變量和局部變量同名問題
當在方法中出現了局部變量和成員變量同名的時候,那麼在方法中怎麼區別局部變量成員變量呢?可以在成員變量名前面加上this.來區別成員變量和局部變量
class Person {
private int age;
private String name;

public void speak() {
	this.name = "小強";
	this.age = 18;
	System.out.println("name=" + this.name + ",age=" + this.age);
}

}

class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.speak();
}
}
3.4.2 對象的內存解釋
我們已經學習瞭如何把生活中的事物使用Java代碼描述,接下來我們分析對象在內存中的分配情況。這裏需要畫圖一步一步演示,嚴格按照畫圖流程講解內存對象創建使用過程。
class Person {
private int age;
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
public class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.setAge(30);
System.out.println(“大家好,今年我” + p.getAge() + “歲”);
}
}
下圖爲程序中內存對象的創建使用過程。

圖1-2 內存對象創建使用過程
程序執行流程說明:
1、 先執行main方法(壓棧),執行其中的 Person p = new Person();
2、 在堆內存中開闢空間,併爲其分配內存地址0x1234,緊接着成員變量默認初始化(age = 0);將內存地址0x1234賦值給棧內中的Person p 變量
3、 繼續執行p.setAge(30)語句,這時會調用setAge(int age)方法,將30賦值爲setAge方法中的“age”變量;執行this.age = age語句,將age變量值30 賦值給成員變量this.age爲30;
4、 setAge()方法執行完畢後(彈棧),回到main()方法,執行輸出語句System.out.println(),控制檯打印p對象中的age年齡值。
 注意:
 this到底代表什麼呢?this代表的是對象,具體代表哪個對象呢?哪個對象調用了this所在的方法,this就代表哪個對象。
 上述代碼中的 p.setAge(30)語句中,setAge(int age)方法中的this代表的就是p對象。
3.4.3 this的應用
學習this的用法之後,現在做個小小的練習。
需求:在Person類中定義功能,判斷兩個人是否是同齡人
class Person {
private int age;
private String name;

public int getAge() {
	return age;
}

public void setAge(int age) {
	this.age = age;
}

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public void speak() {
	System.out.println("name=" + this.name + ",age=" + this.age);
}

// 判斷是否爲同齡人
public boolean equalsAge(Person p) {
	// 使用當前調用該equalsAge方法對象的age和傳遞進來p的age進行比較
	// 由於無法確定具體是哪一個對象調用equalsAge方法,這裏就可以使用this來代替
	/*
	 * if(this.age == p.age) { return true; } return false;
	 */
	return this.age == p.age;
}

}
第4章 綜合案例—隨機點名案例重構
4.1 案例介紹
隨機點名器,即在全班同學中隨機的找出一名同學,打印這名同學的個人信息。
此案例在我們前幾天課程學習中,已經介紹,現在我們要做的是對原有的案例進行升級,使用新的方式來實現。
我們來完成隨機點名器,它具備以下3個內容:
 存儲所有同學姓名
 總覽全班同學姓名
 隨機點名其中一人,打印到控制檯
4.2 案例分析
全班同學中隨機的找出一名同學,打印這名同學的個人信息。
我們對本案例進行分析,得出如下分析結果:
1.存儲全班同學信息(姓名、年齡)
2.打印全班同學每一個人的信息(姓名、年齡)
3.在班級總人數範圍內,隨機產生一個隨機數,查找該隨機數所對應的同學信息(姓名、年齡)並打印
隨機點名器明確地分爲了三個功能。如果將多個獨立功能的代碼寫到一起,則代碼相對冗長,我們可以針對不同的功能可以將其封裝到一個方法中,將完整獨立的功能分離出來。
而在存儲同學姓名時,如果對每一個同學都定義一個變量進行姓名存儲,則會出現過多孤立的變量,很難一次性將全部數據持有。此時,我們採用ArrayList集合來解決多個學生信息的存儲問題。
4.3 重構內容分析
將原來使用的簡單Student類,封裝爲包裝屬性和方法的相對完整的Student類,並將所有訪問屬性的地方改爲通過get/set方法訪問。
重構部分已使用紅色樣色字體表示
4.4 實現代碼步驟
每名學生都擁有多項個人信息,爲了方便管理每個人的信息,我們對學生信息進行封裝,編寫Student.java文件
/**

  • 學生信息類
    */
    public class Student {
    private String name; // 姓名
    private int age; // 年齡

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public int getAge() {
    return age;
    }

    public void setAge(int age) {
    this.age = age;
    }
    }
    上述代碼中,對學生信息(姓名、年齡)進行了封裝。這樣做的好處在於,以後只要找到這名學生,就能夠知道他的每項個人信息了。
    接下來我們編寫CallName.java文件,完成程序的編寫。
     main方法中調用三個獨立方法
    public static void main(String[] args) {
    ArrayList list = new ArrayList(); //1.1創建一個可以存儲多個同學名字的容器
    /*
    * 1.存儲全班同學信息
    /
    addStudent(list);
    /

    * 2.打印全班同學每一個人的信息(姓名、年齡)
    /
    printStudent(list);
    /

    * 3.隨機對學生點名,打印學生信息
    */
    randomStudent(list);
    }

 存儲所有學生的個人信息
/**
* 1.存儲全班同學名字
*/
public static void addStudent(ArrayList list) {
//鍵盤輸入多個同學名字存儲到容器中
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
//創建學生
Student s = new Student();
System.out.println(“存儲第”+i+“個學生姓名:”);
String name = sc.next();
s.setName(name);
System.out.println(“存儲第”+i+“個學生年齡:”);
int age = sc.nextInt();
s.setAge(age);
//添加學生到集合
list.add(s);
}
}
上述方法中,方法參數list中用來表示已存儲所有學生。通過Scanner,完成新學生信息(姓名,年齡)的錄入,並將學生添加到集合中。

 打印全班同學每一個人的信息
/**
* 2.打印全班同學每一個人的信息(姓名、年齡)
*/
public static void printStudent (ArrayList list) {
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(“姓名:”+s.getName() +",年齡:"+s.getAge());
}
}
上述方法中,方法參數list中用來表示已存儲所有學生。通過遍歷集合中的每個元素,得到每個同學信息,並輸出打印。

 隨機對學生點名,打印學生信息
/**
* 3.隨機對學生點名,打印學生信息
*/
public static void randomStudent (ArrayList list) {
//在班級總人數範圍內,隨機產生一個隨機數
int index = new Random().nextInt(list.size());
//在容器(ArrayList集合)中,查找該隨機數所對應的同學信息(姓名、年齡)
Student s = list.get(index);
System.out.println(“被隨機點名的同學:”+s.getName() + “,年齡:” + s.getAge());
}
上述方法中,通過隨機數類Random產生一個從0到集合長度的隨機索引。使用該索引獲取ArrayList集合中對應的值,便得到了全班同學的隨機學生信息並打印。

第5章 總結
5.1 知識點總結
 類與對象
 類,用於描述多個對象的共同特徵,它是對象的模板。
 對象,用於描述現實中的個體,它是類的實例。
 類的定義:使用關鍵字class來定義java中的類
 格式:
class 類名 {
//屬性
數據類型 變量名;

//方法
修飾符 返回值類型 方法名(參數){ }

}
 創建對象:
 格式:
類名 對象名 = new 類名();
 封裝(private關鍵字)
 封裝,把對象的屬性與方法的實現細節隱藏,僅對外提供一些公共的訪問方式
 封裝的體現:
 變量:使用 private 修飾,這就是變量的封裝
 方法:也是一種封裝,封裝了多條代碼
 類: 也是一種封裝,封裝了多個方法
 private關鍵字,私有的意思
 它可以用來修飾類中的成員(成員變量,成員方法)
 private的特點:
 private修飾的成員只能在當前類中訪問,其他類中無法直接訪問
 this關鍵字
 this關鍵字,本類對象的引用
 this是在方法中使用的,哪個對象調用了該方法,那麼,this就代表調用該方法的對象引用
 this什麼時候存在的?當創建對象的時候,this存在的
 this的作用:用來區別同名的成員變量與局部變量(this.成員變量)
public void setName(String name) {
this.name = name;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章