java 的 四 個 基 本 特 性 ——封裝 繼承 多型 抽象

IT女一枚發表於2020-05-01

趕上明天就還是五一c小長假了,準備在這幾天寫幾篇原創文章,供大家一起學習。

首先今天就來好好地嘮一嘮,到底java的那幾個特性都是什麼呢?到底怎麼用呢?相信一定有一些小白對此會有些懊惱,沒關係的,誰還不是從那個時候過來的呢!接下來我來一步一步的由潛到深的談一談我的看法,下面是我要說的內容

1.總體概括

2.概念的理解

3.程式碼示例並且分析

4.個人心得總結

1.總體概括

sequenceDiagram
封裝->>繼承: java的四個基本特性
多型->>抽象: java的四個基本特性

2.概念的理解

  • [1] 封裝:
- 在物件導向程式設計方法中,封裝(英語:Encapsulation)是指一種將抽象性函式介面的實現細節部份包裝、隱藏起來的方法。
封裝可以被認為是一個保護屏障,防止該類的程式碼和資料被外部類定義的程式碼隨機訪問。
要訪問該類的程式碼和資料,必須通過嚴格的介面控制。
封裝最主要的功能在於我們能修改自己的實現程式碼,而不用修改那些呼叫我們程式碼的程式片段。
適當的封裝可以讓程式碼更容易理解與維護,也加強了程式碼的安全性。
通俗一點的可以這麼理解,其實生活中有很多例子的,我來打幾個比方,

例如:我們都使用果QQ這個聊天軟體的,那麼我們們要是想要使用它的話就必須要先註冊

,等註冊好的時候下次我們在直接輸入我們自己設定的密碼就可以了,不需要進行其他的操作

這個過程其實就是把QQ裡面的資料給封裝起來了,防止使用者隨

意更改,只有程式設計師才可以,這樣他便可以保護程式的安全性

也就是說使用者不需要直到QQ他是怎麼執行的,內部是怎麼實現的,對使用者進行隱藏起來了
    還有一種解釋也可以說明:比如說個人計算機有很多元件——CPU 記憶體  磁碟  風扇  等等... 
    
    我們不需要直到他的個個元件之間是怎麼聯絡的,只要知道他們的個個功能是如何實現的就可以了
    
    生活中的例子其實有很多很多 我就不一一說了。(要是還不明白可以私信或者評論區留言)
  • [2] 繼承
  • 繼承”(Inheritance),
繼承是指一個對度象直接使用另一物件的屬性和方法。事實上,我們遇到的很多實體都有繼承的含義。例如,問若把汽車看成一個實體,它可以分成多個子實答體,如:卡車、公共汽車等。這些版子實體都具有汽車的特性,權因此,汽車是它們的"父親",而這些子實體則是汽車的"孩子"(但是孩子也會有自己新產生的特徵)。子類是父類的特殊化,也就是子類的例項(物件)一定是父類的例項 ,但是反過來不一定成立{比如說:一個圓他一定是幾何圖形,但反過來幾何圖形他不一定就是圓呀!還會有很多的呀}
同樣也說一個通俗易懂的例子:比如說,你家的家譜圖,這其實就是一個很明顯的一個繼承關係

你的爸爸繼承了你的爺爺(也就是子類繼承父類),那麼你的爸爸肯定會有可你爺爺相同的特徵,但是呢! 你一定會發現你有一些特徵是不同於你的爺爺的(當然也不同於你的奶奶),你會有你自己獨一無二的特徵,這就是繼承的關係
  • [3] 多型
- 概念:同一操作作用於不同的物件,可以有不同的解釋,產生不同的執行結果,這就是多型性。簡單的說:就是用父類的引用指向子類的物件(變數)。

原因:我們知道,封裝可以隱藏實現細節,使得程式碼模組化;

繼承可以擴充套件已存在的程式碼模組(類);
它們的目的都是為了程式碼重用。而多型除了程式碼的複用性外,還可以解決專案中緊偶合的問題,提高程式的可擴充套件性.。

耦合度講的是模組模組之間,程式碼程式碼之間的關聯度,通過對系統的分析把他分解成一個一個子模組,子模組提供穩定的介面,達到降低系統耦合度的的目的,模組模組之間儘量使用模組介面訪問,而不是隨意引用其他模組的成員變數。

有兩個好處: 1. 應用程式不必為每一個派生類編寫功能呼叫,只需要對抽象基類進行處理即可。大大提高程式的可複用性。//繼承 2. 派生類的功能可以被基類的方法或引用變數所呼叫,這叫向後相容,可以提高可擴充性和可維護性。//多型的真正作用, 可以用在方法的引數中 和 方法的返回型別中。 (子類變數引用父類的變數)
  • [4] 抽象:
就是把一個物件分析出各個屬性, 來替代表達的手法 。
抽 就是抽離;象 ,表復象。表示出來的部分
比如一棵樹。整個一看我們就知道是樹,但是具體是為什麼呢

這制樣就要拿樹和其它東西比出不一樣的地方,這些地方就是抽象出來的。

抽象出來的東西脫離了樹本身,也就變得沒有意義,但是組合起來百就是樹的概念。

比如一棵樹,10米高,樹皮粗糙,樹葉是針形,樹幹很直,等等。這些屬性組合起來會感覺是一顆松樹。但是單獨說 10 米,沒有物件的話,就不知道這個是說的什麼東西。

程式設計上將物件抽象化是很有用的一個方法,能將枯燥的資料與單一度物件對應起來,這樣易於理解,也便於程式設計。

例如在編寫學員管理系統。

學生的定義,首先要有名字,再有性別,問再有學號,等等等等。這些就是抽象出來的屬性

3.程式碼示例並且分析

  • [1] 多型
public class Main {
    public static void main(String[] args) {
        // 給一個有普通收入、工資收入和享受國務院特殊津貼的小夥伴算稅:
        Income[] incomes = new Income[] {
            new Income(3000),
            new Salary(7500),
            new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
    }

    public static double totalTax(Income... incomes) {
        double total = 0;
        for (Income income: incomes) {
            total = total + income.getTax();
        }
        return total;
    }
}

class Income {
    protected double income;
//構造方法
    public Income(double income) {
        this.income = income;
    }
//定義一個方法
    public double getTax() {
        return income * 0.1; // 稅率10%
    }
}
//子類Salary繼承父類Income
class Salary extends Income {
	//構造方法
    public Salary(double income) {
    	//super呼叫了繼承的Salary中的構造方法
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}

class StateCouncilSpecialAllowance extends Income {
    public StateCouncilSpecialAllowance(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        return 0;
    }
}

輸出:800.0

觀察totalTax()方法:利用多型,totalTax()只需和income來打交道它完全不需要知道要StateCouncilSpecialAllowance和Salary的存在,就可以完全計算出得到的稅,如果我們要增加一種稿費的收入,只需要重income中派生出來,然後正確覆蓋getTax方法()就可以,把新的型別傳入給getTax()就可以了
,不需要在重新修改程式碼

可以看出:多型是一個多麼強大的功能,就是允許新增更多型別的子類實現功能擴充套件,卻不需要修改基於父類的程式碼

  • [2] 繼承
public class Bike {
	int speed;
	int brand;
	int colornum;
	//構造方法
	Bike(){
		System.out.println(" call bike constructor");
	}
	public void speedUp() {
		speed = 0;
		System.out.println(" too slow");
	}
	public void presshorn() {
		System.out.println(" I am riding the bike");
	}
}

public class SpeedBike extends Bike{
	/**
	 * super可以呼叫資料成員及其構造方法
	 */
	SpeedBike(){//子類的構造方法
		super();
		super.colornum=12;//子類呼叫資料成員
		super.presshorn();
		System.out.println("call bike construction");	
	}
	public void ride() {
		System.out.println("I am riding the bike");
	}
	/**
	 * super可以呼叫父類的方法
	 */
	public void speedUp() {
		super.speedUp();
		speed+=10;
		System.out.println("so fasyt! ," + " my speed is " + speed + " now");
	}
}

public class DemoBike{
	public static void main(String[] args) {
		SpeedBike aride = new SpeedBike();
				aride.presshorn();
				aride.speedUp();
				aride.ride();
	}
}

輸出:
call bike constructor
 I am riding the bike
call bike construction
 I am riding the bike
 too slow
so fasyt! , my speed is 10 now(這個輸出程式碼就是覆蓋重寫了父類的方法)
I am riding the bike

  • [3] 抽象
    如果一個class定義了方法,但沒有具體執行程式碼,這個方法就是抽象方法,抽象方法用abstract來實現,因為無法執行抽象方法,因此這個類必須申請為抽象類

例如:Person 類定義了抽象方法run(),那麼,在實現子類Student的時候,就必須覆蓋run()方法

public class Main {

	public static void main(String[] args) {
		Person p= new Student();
		p.run();
	}
}
abstract class  Person() {
	public abstract void run();
}
class Student extends Person{
	@overriding
	public void run() {
		System.out.println("Student . run");
	}
}

  • [4] 封裝
package com.fengzhuang;
class Car{
    private String name;//私有成員,名稱
    private String color;//私有成員,顏色
    private String size;//私有成員,大小 
    //得到String型別名字的方法,最後return 返回去
    public String getName(){
        return name;
    }
    public String getColor(){
        return color;
    }
    public String getSize(){
        return size;
    }
    //因為方法名和引數名相同,所有用this
    public void setName(String name){
        this.name=name;
    }
    public void setColor(String color){
    this.color=color;
    }
    public void setSize(String size){
    this.size=size;
    }
}

package com.fengzhuang;
public class Test{
    public static void main(String[] args){
        Car b=new Car();//例項化操作
        b.setName("寶馬");//賦值
        b.setColor("紅色");
        b.setSize("大型");
        //很明顯這些過程看不到如何實現。
        String name=b.getName();//取值
        String color=b.getColor();
        String size=b.getSize();
        //最後輸出結果
        System.out.println(name+":"+color+":"+size);
    }
}

輸出:
寶馬:紅色:大型

解析:因為聲名變數的時候我們已經設定他們幾個為私有變數了,所以我們要是還想在訪問它的話只有通過set這個建立器才可以進行訪問

4.個人心得總結

前面已經說了這麼寫了,那我就最後說一點,總結一下這些吧!

封裝的優勢在於定義只可以在類內部進行對屬性的操作,外部無法對這些屬性指手畫腳,要想修改,也只能通過你定義的封裝方法;
繼承減少了程式碼的冗餘,省略了很多重複程式碼,開發者可以從父類底層定義所有子類必須有的屬性和方法,以達到耦合的目的;
多型實現了方法的個性化,不同的子類根據具體狀況可以實現不同的方法,光有父類定義的方法不夠靈活,遇見特殊狀況就捉襟見肘了

這些是我對這些的理解,希望可以對大家有所幫助。——總而言之,這塊真的是非常重要的,就是java語言的跟呀!大家一定要好好的理解,多琢磨琢磨,多寫寫程式碼,多思考,自然就不難了,就好比"會了不難,難了不會"這個道理是一樣的,寫這篇文章一方面是為了記錄一下子知識點,另一方面也是希望可以幫助那些對這些概念,和程式碼的運用一知半解的朋友們,原創這篇文章真的很不容易寫了好久,希望大家可以多多支援,要是有不懂的可以私信我或者在地下評論,看到了之後我會盡我所能為大家解答的,大家一起學習。(另外明後天我還會陸續連載一些原創文章的要是覺得我寫的對你們有幫助的話,可以關注我一下子,方便查詢 )

大 家 多 多 支 持 ! ! !

相關文章