1.封裝(Encapsulation); 2.繼承(Inheritance); 3.多態(tài)(Polymorphism)
什么是封裝?
封裝就是隱藏實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外提供訪問(wèn)接口
封裝的類(lèi)型有:屬性封裝、方法封裝、類(lèi)封裝、組件封裝、模塊化封裝、系統(tǒng)級(jí)封裝....
封裝的兩個(gè)含義:
1.把對(duì)象的狀態(tài)和行為看成一個(gè)統(tǒng)一的整體,將二者存放在一個(gè)獨(dú)立的模塊中(類(lèi))
2."信息隱藏",把不需要讓外界知道的信息隱藏起來(lái),盡可能隱藏對(duì)象功能實(shí)現(xiàn)細(xì)節(jié),字段
封裝機(jī)制在程序中的體現(xiàn):
把描述對(duì)象的狀態(tài)用字段表示,描述對(duì)象的行為用方法表示,把字段和方法定義在一個(gè)類(lèi)中,并保證外界不能任意更改其內(nèi)部的字段值,也不允許任意調(diào)動(dòng)其內(nèi)部的功能方法
封裝在程序中的一種體現(xiàn):通常將類(lèi)中的成員變量私有化(private),通過(guò)對(duì)外提供方法(set方法,get方法),可對(duì)該變量(xxx)進(jìn)行訪問(wèn)
屬性的封裝
當(dāng)某些屬性或方法被修飾為私有的,那么這些屬性或方法就不能被類(lèi)的外面直接訪問(wèn)
(1).把屬性定義為私有的(只能在本類(lèi)中訪問(wèn))
(2).為屬性提供getter取值方法、setter設(shè)置方法
封裝的優(yōu)點(diǎn)
● 1. 良好的封裝能夠減少耦合
● 2. 類(lèi)內(nèi)部的結(jié)構(gòu)可以自由修改
● 3. 可以對(duì)成員變量進(jìn)行更精確的控制
● 4.模塊化、信息隱藏、實(shí)現(xiàn)細(xì)節(jié)、代碼重用、插件化易于調(diào)試、具有安全性
實(shí)現(xiàn)JAVA封裝步驟
1.修改屬性的可見(jiàn)性來(lái)限制對(duì)屬性的訪問(wèn)(一般為private修飾符)
/**
*定義一個(gè)Person類(lèi)
*隱藏信息
**/
public class Person {
private String name; //定義私有的屬性
private int age; //定義私有屬性
}
這段代碼中,將 name 和 age 屬性設(shè)置為私有的,只能本類(lèi)才能訪問(wèn),其他類(lèi)都訪問(wèn)不了,如此就對(duì)信息進(jìn)行了隱藏
2.對(duì)每個(gè)值屬性提供對(duì)外的公共方法訪問(wèn),也就是創(chuàng)建一對(duì)賦取值方法,用于對(duì)私有屬性的訪問(wèn):
/**
*定義一個(gè)Person類(lèi),隱藏信息并提供訪問(wèn)
**/
public class Person{
private String name; //定義私有的屬性
private int age; //定義私有的屬性
//取得getAge方法
public int getAge(){
return age;
}
//取得getName方法
public String getName(){
return name;
}
//設(shè)置setAge方法
public void setAge(int age){
this.age = age;
}
//設(shè)置setName方法
public void setName(String name){
this.name = name;
}
}
什么是繼承(extends)?
子類(lèi)自動(dòng)共享父類(lèi)數(shù)據(jù)和方法的機(jī)制,這是類(lèi)之間的關(guān)系就是叫做繼承
繼承概念:被繼承的類(lèi)稱(chēng)為父類(lèi)(超類(lèi)),繼承父類(lèi)的類(lèi)稱(chēng)為子類(lèi)(派生類(lèi))
繼承是指一個(gè)對(duì)象直接使用另一個(gè)對(duì)象的屬性和方法,通過(guò)繼承可以實(shí)現(xiàn)代碼重用
super關(guān)鍵字:可以通過(guò)super關(guān)鍵字來(lái)實(shí)現(xiàn)對(duì)父類(lèi)成員的訪問(wèn),用來(lái)引用當(dāng)前對(duì)象的父類(lèi)
使用super調(diào)用父類(lèi)中的屬性,調(diào)用父類(lèi)的方法,調(diào)用父類(lèi)中的構(gòu)造方法
super 表示父類(lèi)對(duì)象的默認(rèn)引用
super如果子類(lèi)要調(diào)用父類(lèi)被覆蓋的實(shí)例方法,可用super作為調(diào)用者調(diào)用父類(lèi)被覆蓋的實(shí)例方法
使用super調(diào)用父類(lèi)方法,使用super調(diào)用父類(lèi)的構(gòu)造方法
this 與super 區(qū)別
| NO. | 區(qū)別 | this | super |
| :-------- | --------:| :------: | :------: |
| 1. | 使用 | 調(diào)用本類(lèi)中的字段或方法 | 從子類(lèi)調(diào)用父類(lèi)中的字段或方法 |
| 2. | 構(gòu)造 | 可以調(diào)用本類(lèi)構(gòu)造方法,且有一個(gè)構(gòu)造方法要作為出口 | 從子類(lèi)調(diào)用父類(lèi)的構(gòu)造方法,不管子類(lèi)如何安排最終一定會(huì)去調(diào)用,默認(rèn)調(diào)用的是父類(lèi)中的無(wú)參構(gòu)造方法 |
| 3. | 要求 | 調(diào)用自身構(gòu)造方法時(shí)放在構(gòu)造方法首行 | 調(diào)用父類(lèi)構(gòu)造方法時(shí)放在子類(lèi)構(gòu)造方法首行 |
| 4. | 特殊 | 表示當(dāng)前對(duì)象 | 表示父類(lèi)對(duì)象 |
方法的覆寫(xiě):方法覆寫(xiě)又稱(chēng)為方法覆蓋
產(chǎn)生原因:當(dāng)父類(lèi)中某個(gè)方法不適合于子類(lèi)時(shí),子類(lèi)出現(xiàn)父類(lèi)一模一樣的方法
調(diào)用被覆蓋的父類(lèi)方法:使用super.方法名(實(shí)參);
方法覆寫(xiě)時(shí)應(yīng)遵循的原則(一同,兩小,一大):
(一同):方法簽名必須相同;
(兩小):子類(lèi)方法的返回值類(lèi)型比父類(lèi)方法的返回值類(lèi)型更小或相等
子類(lèi)方法聲明拋出的異常應(yīng)比父類(lèi)方法申明拋出的異常更小或相等
(一大):子類(lèi)方法的訪問(wèn)權(quán)限應(yīng)比父類(lèi)方法更大或相等
(Overload 重載) 與 (Override 覆寫(xiě)) 區(qū)別
| NO. | 區(qū)別 | (Overload)重載 | (Override)覆寫(xiě) |
| :-------- | --------:| :------: | :------: |
| 1. | 判斷規(guī)則 | 兩同一不同 | 一同兩小一大 |
| 2. | 權(quán)限 | 沒(méi)有權(quán)限要求 | 被覆寫(xiě)的方法不能擁有比父類(lèi)更嚴(yán)格的權(quán)限 |
| 3. | 范圍 | 發(fā)生在一個(gè)類(lèi)中 | 發(fā)生在繼承關(guān)系中 |
| 4. | 術(shù)語(yǔ) | Overload | Override |
| 5. | 多態(tài) | 編譯時(shí)多態(tài) | 運(yùn)行時(shí)多態(tài) |
子類(lèi)對(duì)象實(shí)例化過(guò)程
在繼承操作中,對(duì)于子類(lèi)對(duì)象的實(shí)例化:
子類(lèi)對(duì)象在實(shí)例化之前必須首先調(diào)用父類(lèi)中的構(gòu)造方法之后再調(diào)用自身的構(gòu)造方法
在子類(lèi)進(jìn)行實(shí)例化操作時(shí),首先會(huì)讓其父類(lèi)進(jìn)行實(shí)例化操作(調(diào)用父類(lèi)的構(gòu)造方法),之后子類(lèi)再自己進(jìn)行實(shí)例化操作
子類(lèi)訪問(wèn)父類(lèi);
子類(lèi)不能直接訪問(wèn)父類(lèi)的私有成員,但是子類(lèi)可以調(diào)用父類(lèi)中的非私有方法來(lái)間接訪問(wèn)父類(lèi)的私有成員
在 JAVA中,類(lèi)的繼承是單一繼承,也就是說(shuō),一個(gè)子類(lèi)只能擁有一個(gè)父類(lèi),所以 extends 只能繼承一個(gè)類(lèi)
類(lèi)的繼承格式:在 JAVA中通過(guò) extends 關(guān)鍵字可以申明一個(gè)類(lèi)是從另外一個(gè)類(lèi)繼承而來(lái)的
/**
*定義一個(gè)類(lèi)
**/
class 父類(lèi) {
}
/**
*定義一個(gè)類(lèi)繼承父類(lèi)
**/
class 子類(lèi) extends 父類(lèi) {
}
為什么需要繼承? :接下來(lái)筆者通過(guò)代碼實(shí)例來(lái)說(shuō)明這個(gè)需求
開(kāi)發(fā)汽車(chē)類(lèi),其中汽車(chē)分別為奧迪A6以及奔馳R350,要求如下:
● 奧迪A6:屬性(id,車(chē)名,顏色,速度),方法(汽車(chē)基本信息,汽車(chē)動(dòng)力信息)
● 奔馳R350:屬性(id,車(chē)名,顏色,速度),方法(汽車(chē)基本信息,汽車(chē)動(dòng)力信息)
奧迪A6 汽車(chē)類(lèi)
public class AudiA6 {
private int id; //定義私有汽車(chē)id號(hào)屬性
private String carname; //定義私有車(chē)名屬性
private String colors; //定義私有顏色屬性
private double speed; //定義私有速度屬性
//定義帶參構(gòu)方法
public AudiA6(int id,String carname,String colors,double speed){
this.id = id;
this.carname = carname;
this.colors = colors;
this.speed = speed;
}
//取得getId方法
public int getId(){
return id;
}
//取得getCarname方法
public String getCarname(){
return carname;
}
//取得getColors方法
public String getColors(){
return colors;
}
//取得getSpeed方法
public String getSpeed(){
return speed;
}
//設(shè)置setId方法
public void setId(int Id){
this.id = id;
}
//設(shè)置setCarname方法
public void setCarname(String carname){
this.carname = carname;
}
//設(shè)置setColors方法
public void setColors(String colors){
this.colors = colors;
}
//設(shè)置setSpeed方法
public void setSpeed(double speed){
this.speed = speed;
}
//定義汽車(chē)基本信息方法
public void carinformation(){
System.out.println("汽車(chē)基本信息:" +id+carname+colors); //輸出汽車(chē)id,車(chē)名,顏色
}
//定義汽車(chē)動(dòng)力信息方法
public void information(){
System.out.println("汽車(chē)動(dòng)力信息"+ speed); //輸出速度
}
}
奔馳R350 汽車(chē)類(lèi)
public class MercedesBenzR350 {
private int id; //定義私有汽車(chē)id號(hào)屬性
private String carname; //定義私有車(chē)名屬性
private String colors; //定義私有顏色屬性
private double speed; //定義私有速度屬性
//定義帶參構(gòu)方法
public MercedesBenzR350 (int id,String carname,String colors,double speed){
this.id = id;
this.carname = carname;
this.colors = colors;
this.speed = speed;
}
//取得getId方法
public int getId(){
return id;
}
//取得getCarname方法
public String getCarname(){
return carname;
}
//取得getColors方法
public String getColors(){
return colors;
}
//取得getSpeed方法
public String getSpeed(){
return speed;
}
//設(shè)置setId方法
public void setId(int Id){
this.id = id;
}
//設(shè)置setCarname方法
public void setCarname(String carname){
this.carname = carname;
}
//設(shè)置setColors方法
public void setColors(String colors){
this.colors = colors;
}
//設(shè)置setSpeed方法
public void setSpeed(double speed){
this.speed = speed;
}
//定義汽車(chē)基本信息方法
public void carinformation(){
System.out.println("汽車(chē)基本信息:" +id+carname+colors); //輸出汽車(chē)id,車(chē)名,顏色
}
//定義汽車(chē)動(dòng)力信息方法
public void information(){
System.out.println("汽車(chē)動(dòng)力信息"+ speed); //輸出速度
}
}
<font color="red"&從這兩段代碼我們可以看出來(lái),存在太多重復(fù)代碼,導(dǎo)致后果就是代碼量大且非常多,而且維護(hù)性不高(維護(hù)性主要是后期需要修改的時(shí)候,就需要修改很多的代碼,容易出錯(cuò))</font&
所以要從根本上解決這兩段代碼的問(wèn)題,我們就需要繼承,將兩段代碼中相同的部分提取出來(lái)組成 一個(gè)父類(lèi)
公共的汽車(chē)父類(lèi):
public class Cars {
private int id; //定義私有汽車(chē)id號(hào)屬性
private String carname; //定義私有車(chē)名屬性
private String colors; //定義私有顏色屬性
private double speed; //定義私有速度屬性
//定義帶參構(gòu)方法
public Cars (int id,String carname,String colors,double speed){
this.id = id;
this.carname = carname;
this.colors = colors;
this.speed = speed;
}
//取得getId方法
public int getId(){
return id;
}
//取得getCarname方法
public String getCarname(){
return carname;
}
//取得getColors方法
public String getColors(){
return colors;
}
//取得getSpeed方法
public String getSpeed(){
return speed;
}
//設(shè)置setId方法
public void setId(int Id){
this.id = id;
}
//設(shè)置setCarname方法
public void setCarname(String carname){
this.carname = carname;
}
//設(shè)置setColors方法
public void setColors(String colors){
this.colors = colors;
}
//設(shè)置setSpeed方法
public void setSpeed(double speed){
this.speed = speed;
}
//定義汽車(chē)基本信息方法
public void carinformation(){
System.out.println("汽車(chē)基本信息:" +id+carname+colors); //輸出汽車(chē)id,車(chē)名,顏色
}
//定義汽車(chē)動(dòng)力信息方法
public void information(){
System.out.println("汽車(chē)動(dòng)力信息"+ speed); //輸出速度
}
}
<font color="red"&這個(gè)Cars類(lèi)就可以作為一個(gè)父類(lèi),然后奧迪A6汽車(chē)類(lèi)和奔馳R350汽車(chē)類(lèi)繼承Cars公共汽車(chē)類(lèi)之后,就具有父類(lèi)當(dāng)中的屬性和方法,子類(lèi)就不會(huì)存在重復(fù)的代碼,維護(hù)性也提高,代碼也更加簡(jiǎn)潔,提高代碼的復(fù)用性(復(fù)用性主要是可以多次使用,不用再多次寫(xiě)同樣的代碼)</font&
繼承之后的代碼:
奧迪A6汽車(chē)類(lèi) 繼承Cars公共類(lèi):
public class AudiA6 extends Cars {
//帶參構(gòu)造方法
public AudiA6(int id,String carname,String colors,double speed) {
super(id, carname, colors, speed);
}
//定義汽車(chē)基本信息方法
public void carinformation(){
super.carinformation(); //super調(diào)用父類(lèi)的方法
}
//定義汽車(chē)動(dòng)力信息方法
public void information(){
super.carinformation(); //super調(diào)用父類(lèi)的方法
}
}
奔馳R350汽車(chē)類(lèi) 繼承Cars公共類(lèi):
public class MercedesBenzR350 extends Cars {
public MercedesBenzR350(int id,String carname,String colors,double speed) {
super(id, carname, colors, speed);
}
//定義汽車(chē)基本信息方法
public void carinformation(){
super.carinformation(); //super調(diào)用父類(lèi)的方法
}
//定義汽車(chē)動(dòng)力信息方法
public void information(){
super.carinformation(); //super調(diào)用父類(lèi)的方法
}
}
繼承的特性
● 子類(lèi)擁有父類(lèi)非private的屬性,方法
● 子類(lèi)可以擁有自己的屬性和方法,即子類(lèi)可以對(duì)父類(lèi)進(jìn)行擴(kuò)展
● 子類(lèi)可以用自己的方式實(shí)現(xiàn)父類(lèi)的方法
● Java的繼承是單繼承,但是可以多重繼承,單繼承就是一個(gè)子類(lèi)只能繼承一個(gè)父類(lèi)
多重繼承就是,例如A類(lèi)繼承B類(lèi),B類(lèi)繼承C類(lèi),所以按照關(guān)系就是C類(lèi)是B類(lèi)的父類(lèi),B類(lèi)是A類(lèi)的父類(lèi)
這是java繼承區(qū)別于C++繼承的一個(gè)特性
● 提高了類(lèi)之間的耦合性(繼承的缺點(diǎn),耦合度高就會(huì)造成代碼之間的聯(lián)系)
什么是多態(tài)?: 多態(tài)性指同一個(gè)實(shí)體同時(shí)具有多種形式
多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力,多態(tài)性是對(duì)象多種表現(xiàn)形式的體現(xiàn)
譯時(shí)的類(lèi)型由聲明該變量時(shí)使用的類(lèi)型決定
運(yùn)行時(shí)的類(lèi)型由實(shí)際賦給變量的對(duì)象決定,如果編譯時(shí)類(lèi)型和運(yùn)行時(shí)類(lèi)型不同,就出現(xiàn)多態(tài)性
生活中多態(tài)的例子:
比如我們說(shuō)"寵物"這個(gè)對(duì)象,它就有很多不同的表達(dá)或?qū)崿F(xiàn),比如有小貓、小狗、等等
那么我到寵物店說(shuō)"請(qǐng)給我一只寵物",服務(wù)員給我小貓、小狗或者蜥蜴都可以,我們就說(shuō)"寵物"這個(gè)對(duì)象就具備多態(tài)性
多態(tài)的實(shí)現(xiàn)方式:
1.方法的重載(同一個(gè)類(lèi)里面,返回值相同,方法名相同,參數(shù)的個(gè)數(shù)不同),重寫(xiě)(發(fā)生在子類(lèi)與父類(lèi)關(guān)系中)
2.對(duì)象的多態(tài)性:是從繼承關(guān)系中的多個(gè)類(lèi)而來(lái),引用變量類(lèi)型轉(zhuǎn)換
向上轉(zhuǎn)型:將子類(lèi)實(shí)例化轉(zhuǎn)為父類(lèi)實(shí)例格式:
向上轉(zhuǎn)型(子類(lèi)→父類(lèi)):(自動(dòng)完成) 父類(lèi)名稱(chēng) 父類(lèi)對(duì)象 = 子類(lèi)實(shí)例 ;
向下轉(zhuǎn)型(父類(lèi)→子類(lèi)):(強(qiáng)制完成) 子類(lèi)名稱(chēng) 子類(lèi)對(duì)象 = (子類(lèi)名稱(chēng))父類(lèi)實(shí)例 ;
3.接口
● 生活中的接口最具代表性的就是插座,例如一個(gè)三接頭的插頭都能接在三孔插座中,因?yàn)檫@個(gè)是每個(gè)國(guó)家都有各自規(guī)定的接口規(guī)則,有可能到國(guó)外就不行,那是因?yàn)閲?guó)外自己定義的接口類(lèi)型
● JAVA中的接口類(lèi)似于生活中的接口,就是一些方法特征的集合,但沒(méi)有方法的實(shí)現(xiàn)
4.抽象類(lèi)和抽象方法
多態(tài)的作用:把不同的子類(lèi)對(duì)象都當(dāng)作父類(lèi)來(lái)看,可以屏蔽不同子類(lèi)對(duì)象之間的差異,寫(xiě)出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化,只修改方法的實(shí)現(xiàn),不必修改方法的聲明,繼承是多態(tài)產(chǎn)生的前提條件
多態(tài)的分類(lèi):編譯時(shí)多態(tài):方法重載,運(yùn)行時(shí)多態(tài):方法覆寫(xiě)
多態(tài)的優(yōu)點(diǎn)
● 1. 消除類(lèi)型之間的耦合關(guān)系
● 2. 可替換性
● 3. 可擴(kuò)充性
● 4. 接口性
● 5. 靈活性
● 6. 簡(jiǎn)化性
更多建議: