面向物件、類和物件、封裝---------私有private、this關鍵字
1、面向物件和麵向過程
面向物件是讓誰幹什麼
面向過程是按什麼順序來幹(幹活過程都有參與)
所以在工作中,面向物件更好。
例如:
以打掃辦公室為例:面向過程就是將掃地、拖地、擦玻璃、擦門窗這幾件事情排好(做好)順序,先幹啥再幹啥,需要按照順序一件一件的參與幹活‘
面向物件就是打掃衛生時,小李拖地,小楊擦玻璃,小張擦門窗,小孫擦門窗,每個人幹不同的活,最後將辦公室打掃乾淨;
再比如:買電腦:面向過程就是查詢想要的型號,詢價零件、購買、組裝、搬回家。在整個過程中我們參與了每一個細節,並且會感覺相當累。
面向物件就是找個專門懂得人幫忙檢視配置、組裝等,不需要親歷親為具體怎麼做,只要告訴這個人我們想要的具體需求即可。
面向過程思維方式中更多的體現的是執行者(自己做事情),面向物件中更多的體現是指揮者(指揮物件做事情)。
2、類和物件
(1)類在需求中的使用--------------類的定義方式及在程式碼中的實現
已將大象關進冰箱這個需求來舉例:
需求:把大象裝冰箱裡
物件:大象、冰箱
分三步:
第一步開啟冰箱門
第二部將大象裝進去
第三步關閉冰箱門
冰箱物件具備如下功能:
冰箱開啟
冰箱儲存
冰箱關閉
------------1、建立冰箱的物件
冰箱 bx = new 冰箱();
-----------2、呼叫冰箱的功能
物件.功能();
bx.開啟();
bx.儲存
bx.關閉();
程式碼就是:
public class Daxiang { }//先定義一個Daxiang類
public class Bingxiang {//再定義一個 Bingxiang,類名大寫public void open(){//方法
System.out.println("冰箱打開了"); } public void save(Daxiang dx){ System.out.println("將大象裝進來"); } public void close(){ System.out.println("冰箱關閉了"); } }
publicclass Test {//定義一個測試的類 public static void main(String[] args) { Bingxiang bx = new Bingxiang();//建立物件,new 一個物件 Daxiang dx = new Daxiang(); bx.open();//呼叫方法 bx.save(dx); bx.close(); } }
l定義類的格式
public class 類名 {
//可編寫0至n個屬性
資料型別 變數名1;
資料型別 變數名2;
//可編寫0至n個方法
修飾符 返回值型別 方法名(引數){
執行語句;
}
}
再以汽車為例:
汽車(事物)的特點(屬性):
汽車的顏色。
輪胎個數。
事物的(功能):
執行。
-----------即:
--------------小汽車 {
------------------------------顏色;
------------------------------輪胎個數;
---------------------執行() { }
---------------------}
public class Car { String color;//顏色 int number;--------------成員變數 public void run() {//定義一個方法, System.out.println(color + ":" + number); } }
類的真正意義就是在描述事物。屬性和功能統稱為事物中的成員。
事物的成員分為兩種:成員屬性和成員功能。
成員屬性在程式碼中的體現就是成員變數
成員功能在程式碼中的體現就是成員方法
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)區域性變數和成員變數的區別
第一個:定義位置不同:成員變數是在類中,區域性變數是在方法中或者{}語句裡面
第二個:在記憶體中的位置不同:區域性變數在棧中的方法裡,成員變數在堆中的類中
第三個:生命週期不同:區域性變數隨著方法的執行而出現在棧中,隨著方法的彈棧而消失;成員變數則是隨著類在儲存在堆中,物件消失,成員變數才消失
第四個:初始化不同:成員變數隨著類進入堆中,會被預設賦值為0或者null等,區域性變數沒有初始化值,手動賦值才行
3、封裝
1、封裝概述
封裝:在方法中,就是將具體的功能封裝到方法中。在物件中就是將方法封裝到類中。
面向物件的三個基本特徵:封裝、繼承、多型
①封裝的表現:
-------------方法就是一個最基本的封裝體
-------------類其實也是一個封裝體
②封裝的好處:
---------------提高了程式碼的複用性
--------------隱藏了實現細節,向外部提供訪問的方式,便於呼叫者使用,這是封裝的核心,也可以說是封裝的概念。
---------------提高了安全性
③封裝的舉例說明:就拿桌上型電腦的主機來說,主機有cpu、硬碟、主機板等構成,如果主機外部不加一個外殼,那麼內部的組成部分就裸露在外部,會變得很不安全
外殼就可以看成是一個封裝,其上的USB等介面可以看成是其提供的讓外部訪問的方式。
(2)私有private
類中的屬性的行為可以任意訪問和使用,因此要使用關鍵字也是一個修飾符(私有private)。
例如:
package demo01; //privat:私有,可以修飾類,被修飾的成員只能在本類中訪問 public class Person { private int age;---------------私有化 private String name; //對外提供公共訪問方式 public void setage(int a){ if(a>=0&&a<130){ age=a; }else { age=0; } } public int getage(){//-----------------------滑鼠右擊------------Source------Generate Getters and Setter return age; } public void setname(String n){ name=n; } public String getname(){ return name; } public void speak(){ System.out.println("我叫"+name+",今年"+age+"歲"); } }
package demo01; public class Text { public static void main(String[] args) { Person p=new Person(); p.setname("佩奇");//-------------通過方法賦值。訪問私有的物件屬性 p.setage(18); p.speak(); System.out.println(p.getage()); System.out.println(p.getname()); } }
l 總結:
類中不需要對外提供的內容都私有化,包括屬性和方法。
以後再描述事物,屬性都私有化,並提供setXxx getXxx方法對其進行訪問。
l 注意:私有僅僅是封裝的體現形式而已。
(3)this關鍵字
在方法中出現區域性變數和成員變數同名時,可以新增this關鍵字來進行區分,可以在成員變數名前面加上this.來區別成員變數和區域性變數
Public 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); } }
Public class PersonDemo { public static void main(String[] args) { Person p = new Person(); p.speak(); } }
物件的記憶體解釋
程式執行流程說明:
1、首先在資料和方法共享區讀取.class檔案,main方法。
2、 先執行main方法(壓棧),執行其中的 Person p = new Person();
3、看到new一個物件則 在堆記憶體中開闢空間,併為其分配記憶體地址0x000,緊接著成員變數預設初始化(age = 0);將記憶體地址0x000賦值給棧內中的Person p 變數
4、繼續執行p.setAge(30)語句,這時會呼叫setAge(int age)方法,將30賦值為setAge方法中的“age”變數;執行this.age = age語句,將age變數值30 賦值給成員變數this.age為30;
5、setAge()方法執行完畢後(彈棧),回到main()方法,執行輸出語句System.out.println(),控制檯列印p物件中的age年齡值。
4、繼承
(1)繼承的概述:
在程式中,繼承描述的是事物之間的所屬關係,通過繼承可以使多種事物之間形成一種關係體系。
例如:
類的繼承是指在一個現有類的基礎上去構建一個新的類,構建出來的新類被稱作子類,現有類被稱作父類,子類會自動擁有父類所有可繼承的屬性和方法。
格式:
public class 子類 extends 父類 { }
整合的舉例:
package damo03; public class Fu { int a=6; }
package damo03; //在繼承中,成員變數的特點: //如果父類成員變數和子類成員變數同名,那麼呼叫的是子類的成員變數 //在繼承中,子類只能繼承父類可繼承的成員,私有化的成員,可以繼承,但是沒法使用和操作,相當於沒繼承 public class ZI extends Fu{//------------------繼承父類 int a=2; public void speak(){ int a=3; System.out.println(this.a); System.out.println(super.a); } }
package damo03; public class Text1 { public static void main(String[] args) { ZI bb=new ZI(); bb.speak(); } }
Zi類通過extends關鍵字繼承了Fu類。
子類雖然沒有定義int a=1;的屬性和work()方法,但是卻能訪問這這個成員。這就說明,子類在繼承父類的時候,會自動擁有父類的成員。
繼承的好處與注意事項:
好處:
1、提高了程式碼的複用性,
2、繼承的出現讓類與類之間產生了關係,提供了多型的前提。
注意事項:
1、在Java中,類只支援單繼承,不允許多繼承,也就是說一個類只能有一個直接父類
class A{}
class B{}
class C extends A,B{} // C類不可以同時繼承A類和B類
2、多個類可以繼承一個父類
class A{}
class B extends A{}
class C extends A{} // 類B和類C都可以繼承類A
(2)子父類中成員變數的特點
----------------Fu類中的成員變數是非私有的,子類中可以直接訪問,若Fu類中的成員變數私有了,子類是不能直接訪問的。當子父類中出現了同名成員變數時,在子類中若要訪問父類中的成員變數,必須使用關鍵字super來完成。super用來表示當前物件中包含的父類物件空間的引用。
在子類中,訪問父類中的成員變數格式:
super.父類中的成員變數
class Fu { //Fu中的成員變數。 int num = 5; }
class Zi extends Fu { //Zi中的成員變數 int num = 6; void show() { //子父類中出現了同名的成員變數時 //在子類中需要訪問父類中非私有成員變數時,需要使用super關鍵字 //訪問父類中的num System.out.println("Fu num="+super.num); //訪問子類中的num2 System.out.println("Zi num2="+this.num); } }
class Demo5 { public static void main(String[] args) { Zi z = new Zi(); //建立子類物件 z.show(); //呼叫子類中的show方法 } }
(3)子類繼承父類的的方法特點:直接繼承和重寫
當在程式中通過物件呼叫方法時,會先在子類中查詢有沒有對應的方法,若子類中存在就會執行子類中的方法,若子類中不存在就會執行父類中相應的方法。
class Fu{-----------------------------------------------------------------------------父類 public void show(){---------------------------------------------------------------show方法 System.out.println("Fu類中的show方法執行"); } } class Zi extends Fu{-------------------------------------------------------------------子類繼承父類的方法 public void show2(){---------------------------------------------------------------子類的show2方法 System.out.println("Zi類中的show2方法執行"); } } public class Test{ public static void main(String[] args) { Zi z = new Zi(); z.show(); //-------------------------------------------------------------------子類中沒有show方法,但是可以找到父類方法去執行 z.show2();----------------------------------------------------------------------父類中沒有show方法,就執行的父類中的方法 } }
成員方法特殊情況——覆蓋
子類中出現與父類一模一樣的方法時,會出現覆蓋操作,也稱為override重寫、複寫或者覆蓋。方法重寫
class Zi extends Fu { //子類複寫了父類的show方法 public void show() { System.out.println("Zi show"); } }
l 方法重寫(覆蓋)的應用:
當子類需要父類的功能,而功能主體子類有自己特有內容時,可以重寫父類中的方法,這樣,即沿襲了父類的功能,又定義了子類特有的內容。
例如:增加功能
比如手機,當描述一個手機時,它具有發簡訊,打電話,顯示來電號碼功能,後期由於手機需要在來電顯示功能中增加顯示姓名和頭像,這時
可以重新定義一個類描述智慧手機,並繼承原有描述手機的類。並在新定義的類中覆蓋來電顯示功能,在其中增加顯示姓名和頭像功能。
class Phone{--------------------------------------------屬性 public void sendMessage(){ System.out.println("發簡訊"); } public void call(){ System.out.println("打電話"); } public void showNum(){ System.out.println("來電顯示號碼"); } }
//智慧手機類 class NewPhone extends Phone{-----------------------繼承父類屬性 //覆蓋父類的來電顯示號碼功能,並增加自己的顯示姓名和圖片功能 public void showNum(){ //呼叫父類已經存在的功能使用super super.showNum(); //增加自己特有顯示姓名和圖片功能 System.out.println("顯示來電姓名"); System.out.println("顯示頭像"); } }
public class Test { public static void main(String[] args) { new NewPhone().showNum(); } }
注意:
l 子類方法覆蓋父類方法,必須要保證許可權大於等於父類許可權。
l 寫法上稍微注意:必須一模一樣:方法的返回值型別 方法名 引數列表都要一樣。
總結:當一個類是另一個類中的一種時,可以通過繼承,來繼承屬性與功能。如果父類具備的功能內容需要子類特殊定義時,進行方法重寫。