1. 程式人生 > >Java應用程式開發學習之繼承

Java應用程式開發學習之繼承

面對物件程式語言有三類特性,分別是封裝性、繼承性以及多型性。

本節就來簡單介紹下Java的繼承。

一、繼承的簡單介紹、特點、規則

繼承是多型的前提,如果沒有繼承,就沒有多型。
繼承主要解決的問題是:共性抽取(解決重複程式碼的問題)。

Java繼承知識點裡兩個重要的名詞:父類和子類

父類:也叫做基類、超類
子類:也叫派生類

Java繼承關係當中的特點:
1、子類可以擁有父類的內容。
2、子類還可以擁有自己專有的內容。

子類方法的返回值必須小於等於父類方法的返回值範圍。
Object類是所有類的公共最高父類(祖宗類)
java.lang.Object類是所有類的公共最高父類,java.lang.String就是Object的子類

子類方法的許可權必須[大於等於]父類方法的許可權修飾符
 public > protected > (default) > private
 這裡(default)不是關鍵字default,而是什麼都不寫,留空。

在Java繼承關係中,子類就是一個父類,也就是說,子類可以被當做父類看待
例如父類是員工,子類是講師,那麼講師就是一個員工,關係is->a。

二、怎麼來定義父子類之間的繼承關係

一、定義父類的格式:(就是一個普通的類定義)
public class 父類名稱
{
	//...
}

二、定義子類的格式:
public class 子類名稱 extends 父類名稱
{
	//...
}

注意:父類只能使用父類的東西,沒有任何子類的內容。
           子類既可以使用父類繼承下來的東西,也可以用子類本身的東西。

1、在父子類的繼承關係中,如果成員變數重名,則建立子類物件時,訪問有兩種方式:
(1)直接通過子類物件訪問成員變數
    建立的時候等號左邊是誰,就優先呼叫誰,沒有則向上找(只能由子到父這樣的順序)
(2)間接通過成員方法訪問成員變數
    該方法屬於誰,就優先呼叫誰,沒有則向上找(只能由子到父這樣的順序)
2、在父子類的繼承關係中,建立子類物件,訪問成員方法的規則:


    建立的物件是誰,就優先用誰,如果沒有則向上找
    注意事項:
    無論成員方法還是成員變數,如果沒有都是向上找父類,絕對不會向下找子類的。   

三、方法重寫

概念:在繼承關係當中,方法的名稱一樣,引數列表也一樣。
方法重寫和方法過載的區別:
方法重寫是方法的名稱一樣,引數列表也一樣,也就是覆蓋、覆寫。
方法過載是方法的名稱一樣,引數列表不一樣
方法的覆蓋重寫特點:建立的是子類物件,則優先用子類方法。

@Override
可以把這個寫在方法前面,用來檢測是不是有效的覆蓋重寫,如果不是重寫,會報錯。(可選)

方法重寫的應用場景:
設計原則:
對於已經投入使用類,儘量不要進行修改
推薦一個新的類,來重複利用其中共性內容,並且新增改動新內容。例如:

定義子類的xxx方法
void xxx()        
{    
    super.xxx();     //把父類的xxx()方法拿過來重複利用
    
    //子類再來新增更多內容。
    xx();
    xxxxx();
    xxxxxxx();
}

繼承關係中,父子類構造方法的訪問特點:
1.子類構造方法當中有一個預設隱藏的super呼叫,所以一定是先呼叫的父類構造方法,再呼叫子類構造方法。
2.可以通過super關鍵字來子類構造呼叫父類過載構造。
3.只有子類構造方法,才能呼叫父類構造方法
4.super的父類構造呼叫,必須是子類構造方法的第一個語句,不能一個子類構造呼叫多次super構造。
總結:
子類必須呼叫父類構造方法,不寫則贈送super();寫了則用寫了指定的super呼叫,super只能有一個,還必須是第一個。

父類的構造方法:(有參)
public xxx(int xx)
{

}

子類的構造方法:(無參)
public xxx()
{
    super(10);
    //..
    //..
}

四、super關鍵字的用法

1、在子類的成員方法中,訪問父類的成員變數。
     System.out.println(super.xx);
2、在子類的成員方法中,訪問父類的成員方法。
     super.method();
3、在子類的構造方法中,訪問父類的構造方法。

     public simple_member(int Money_Balance , String Name)
     {
        super(Money_Balance,Name);
     }

五、this關鍵字的三種用法

1、在本類的成員方法中,訪問本類的成員變數。
2、在本類的成員方法中,訪問本類的另一個成員方法。
3、在本類的構造方法中,訪問本類的另一個構造方法。
     在第三種用法中要注意:
     this(...)呼叫也必須是構造方法的第一個語句,唯一一個
     this(xxx);
     super和this兩種構造呼叫,不能同時使用

六、Java繼承的特點

參考傳智Java課程學習如下:

七、抽象

如果父類當中的方法不確定如何進行{}方法體實現,那麼這就應該是一個抽象方法。

格式:
抽象方法:加上abstract關鍵字,然後去掉大括號,直接分號結束。
抽象類:抽象方法所在的類,必須是抽象類。
抽象類可以定義普通成員方法。
public abstract class xxx
{
    //這是一個抽象方法,但是具體是什麼,不確定。
    public abstract void xxxx();
}

如何使用抽象類和抽象方法
1.不能直接建立new抽象類物件。
2.必須用一個子類來繼承抽象父類。
3.子類必須覆蓋重寫父類當中所有的抽象方法。
   覆蓋重寫(實現),去掉抽象方法的abstract關鍵字,然後補上方法大括號(實現)。
4.建立子類物件進行使用。


注意事項:
1.抽象類不能建立物件,如果建立,編譯無法通過而報錯。只能建立其非抽象子類的物件。
2.抽象類中,可以有構造方法,是供子類建立物件時,初始化父類成員使用的。
3.抽象類中,不一定包含抽象方法,但是有抽象方法的類就必須是抽象類。(應用:設計模式的介面卡模式)
4.抽象類的子類,必須重寫抽象父類中所有的抽象方法,否則,編譯無法通過而報錯,除非該子類也是抽象類。

下面來看一個Java繼承的應用,發紅包的案例:

使用者類定義:

使用者類主要定義了一些其它子類公有的資訊,達到程式碼的複用功能。

package demo;
public class User {
	
	//使用者餘額定義
	private int Money_Balance ;
	//使用者名稱稱定義
	private String Name ;
	
	public User(){
		
	}
	
	public User(int Money_Balance , String Name)
	{
		this.Money_Balance = Money_Balance ;
		this.Name = Name ;
	}
	
	//獲取成員名稱
	public String Get_Name()
	{
		return this.Name ;
	}
	
	//設定餘額
	public void Set_Money_Balance(int Money_Balance)
	{
		this.Money_Balance = Money_Balance ; 
	}
	
	//獲取餘額
	public int Get_Money_Balance()
	{
		return this.Money_Balance ;
	}
	
	//列印成員名稱和餘額
	public void show()
	{
		System.out.println(this.Name+"有"+this.Money_Balance+"元錢");
	}
}

群主類定義:

群主類主要實現的是發紅包的方法。

package demo;

import java.util.ArrayList;

public class Lord extends User{

	public Lord(int Money_Balance , String Name)
	{
		super(Money_Balance,Name);
	}
	
	//顯示資訊
	public void show()
	{
		super.show();
	}
	
	//發紅包的方法
	public  ArrayList<Integer> send(int totalMoney,int count)
	{
		ArrayList<Integer> list = new ArrayList<>();
		int Integer_money 		= totalMoney / count ;
		int remainder_money     = totalMoney % count ;
		//判斷Lord有多少錢
		if(totalMoney > super.Get_Money_Balance())
		{
			System.out.println("餘額不足");
			return list ;
		}
		//群主一共有多少錢,要發多少錢就從總數里扣掉這筆要發的錢
		super.Set_Money_Balance(super.Get_Money_Balance()-totalMoney);
		//總工要發count個紅包
		for(int i = 0 ; i < count ; i++)
		{
			//能夠取整的
			if(i < count - 1)
				list.add(Integer_money);
			//不能夠取整的放在最後一個紅包裡
			else
				list.add(Integer_money+remainder_money);
		}		
		return list;
	}
}

普通成員類定義:

普通成員主要實現收紅包的方法。

package demo;

import java.util.ArrayList;
import java.util.Random;

public class simple_member extends User{

	public simple_member(int Money_Balance , String Name)
	{
		super(Money_Balance,Name);
	}
	
	//顯示資訊
	public void show()
	{
		super.show();
	}
	
	//收紅包的方法
	public  void receive(ArrayList<Integer> list)
	{
		Random r = new Random();
		//得到一個ArrayList的隨機索引
		int rand_index = r.nextInt(list.size());
		//獲取員工當前有多少錢
		int member_money = super.Get_Money_Balance();
		//得到移除索引所對應的數值
		int delet_money = list.remove(rand_index);
		//並且得到的紅包給員工本人,做加法
		super.Set_Money_Balance(member_money+delet_money);
		
	}
}

主程式編寫:

package demo;
import java.util.ArrayList;

public class Red_envelopes_main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int money = 100 ;
		Lord boss = new Lord(100,"老闆");
		simple_member worker1 = new simple_member(0,"員工1");
		simple_member worker2 = new simple_member(0,"員工2");
		simple_member worker3 = new simple_member(0,"員工3");
		boss.show();
		worker1.show();
		worker2.show();
		worker3.show();
		//老闆發紅包
		ArrayList<Integer> list_read = boss.send(20, 3);
		boss.show();
		//員工收紅包
		worker1.receive(list_read);
		worker2.receive(list_read);
		worker3.receive(list_read);
		worker1.show();
		worker2.show();
		worker3.show();
		
	}
}

執行結果:

參考資料:傳智播客Java視訊學習課程筆記