1. 程式人生 > >JavaSE之面向物件程式設計—抽象類與介面—— 1

JavaSE之面向物件程式設計—抽象類與介面—— 1

                                                                                        抽象類的定義與使用


一、抽象類的概念
抽象類就是在類裡面含有抽象方法,那麼什麼又是抽象方法呢,抽象方法就是一個方法但是它只有方法名、沒有函式體,並且用abstact來修飾就叫做抽象方法。抽象類裡面必須含有抽象方法,並且這個抽象類也需要abstract來修飾。
注意:在抽象方法中,如果只有abstract來修飾它但是呢在這個類裡面並沒有抽象方法,這個類也叫做抽象類,同樣它也是不可以進行例項化的。
栗子:

abstract class Person{
	private String name;
	public void print(){
		System.out.print("這是抽象類的普通方法");
	}
}

下面我們來看一下抽象類的栗子:

abstract class Person{
	private String name;
	public void print(){
		System.out.print("這是抽象類的普通方法");
	}
	public abstract void getPersonInfo();//只有含函式的名字但是沒有函式體——>抽象方法
}
public class Chouxiang{
	public static void main(String[] args){
		Person p1=new Person();//錯誤的,抽象方法不可以例項化
		p1.print();
	}
}

在這裡插入圖片描述
通過上面的這個栗子我們可以發現對於抽象類它是不可以例項化物件的。並且它沒有什麼特別之處,只是相對於普通類而言多了抽象方法。
二、對於抽象類的使用原則
1.所有的抽象類必須有子類,因為抽象類是不可以直接例項化的,就不能建立物件,要對它建立物件,需要通過它的子類來實現,它的子類必須要事項它的抽象方法。
2.抽象類的子類必須實現抽象方法,實現抽象方法的這個過程就叫做方法覆寫,將父類沒有完成的事情做完。
3.抽象類的父類想要建立物件得通過多型的方法,通過子類建立物件。
4.private和abstract不可以同時使用,因為如果用private修飾了一個方法,那麼這個方法子類將不可以看見,不可以訪問了,不能訪問的方法那麼子類就不可以去實現了,最後這個抽象方法不能實現不能建立物件,就沒有存在的意義了。但是我們的屬性還是需要private修飾的,因為這樣才可以體現封裝的特性。
一個完成的抽象類及它的使用:
情況1:

//使用抽象類
abstract class Person{
	private String name;
	public String getName(){
		return this.name;
	}
	public void setName(String name){
		this.name=name;
	}
	//下面定義一個抽象方法,只有方法名沒有方法體
	public abstract void getPersonInfo();
}
//Student類繼承Person類,是它的子類
class Student extends Person{
	//實現抽象類中的抽象方法
	public void getPersonInfo(){
		System.out.println("I am a student");
	}
}
public class Chouxiang{
	public static void main(String[] args){
		Person p=new Student();//向上轉型,體現了多型
		p.getPersonInfo();
	}
}

在這裡插入圖片描述
情況2:

//情況2:
abstract class Person{
	private String name;
	public String getName(){
		return name;
	}
	public void setName(){
		this.name=name;
	}
	//下面定義抽象方法
	public abstract void getPersonInfo();
	
	public static Person getInstance(){//取得A類的物件
		class Student extends Person{//定義方法內部類
			public void getPersonInfo(){//實現抽象類中的抽象方法
				System.out.println("I am a student");
			}
		}
        return new Student();//建立的一個子類的匿名物件		
	}
}
public class Chouxiang{
	public static void main(String[] args){
		Person p=Person.getInstance();
		p.getPersonInfo();//被子類覆寫以後的方法
	}
}

在這裡插入圖片描述
兩種方法實現的是同樣的功能,但是我們一般採取的是第一種做法。
三、抽象類相關規定
對於抽象類我們的定義限定只是需要它有抽象方法,但是對於其他的我們並沒有做相關的要求規定,那麼在抽象類中我們同樣是可以定義構造方法的,並且黨子類繼承抽象類以後對於構造方法的執行還是按照之前我們規定的順序執行,先執行父類的構造方法,然後再執行子類的構造方法。
栗子:在抽象方法中定義構造方法

//在抽象方法中定義構造方法
abstract class Person {
	private String name;
	public Person(){//定義構造方法
		System.out.println("這是抽象父類的構造方法");
	}
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name=name;
	}
	public abstract void getPersonInfo();//定義的一個抽象方法
}
class Student extends Person{
	public Student(){
		super();//繼承後在構造方法中首先要呼叫父類的構造方法,此時只有無參構造方法,可以不寫系統預設呼叫
		System.out.println("這是子類的構造方法");
	}
	public void getPersonInfo(){//實現抽象類的抽象方法
		System.out.println("這是父類的抽象方法通過子類實現了");
	}
}

public class Chouxiang{
	public static void main(String[] args){
	Person p=new Student();
	p.getPersonInfo();//其實質開闢的空間是子類的,所以他們兩個的輸出結果是相同的
	System.out.println("================");
	Student t=new Student();
	t.getPersonInfo();
	}
}

在這裡插入圖片描述
下面我們來看一段程式碼:

//一段特殊程式碼
abstract class A{
	public A(){//3.呼叫父類的無參構造
		this.print();//4.呼叫被子類覆寫的方法
	}
	public abstract void print();
}
class B extends A{
	private int num = 100;
	public B(int num){//2.呼叫子類的構造方法
		super();//3.執行父類的無參構造
		this.num=num;//7.給子類物件中的屬性進行賦值
	}
	public void print(){//5.此時子類物件還沒有被例項化,對應的值還是預設值
		System.out.println(this.num);//6.輸出預設值
	}
}
public class Chouxiang{
	public static void main(String[] args){
		new B(30).print();//1.例項化子類物件
	}
}

在這裡插入圖片描述
對於以上程式碼的結果我們做以下分析:
首先這個程式碼的執行順序已經在程式碼中標號;其次為什麼第一個輸出的結果是0而不是我們的預設值100呢?因為在程式窒息感的時候是從main方法處開始執行的,在這段程式碼中,跳到B的例項化的時候又跳到了A的例項化,所以在第一次輸出的時候B還沒有例項化,這個時候子類還沒有進行一系列的初始化工作,所以不是100,而是系統預設值0。所以我們對物件的例項化需要注意:
1.進行類的載入
2.進行類物件的空間開闢
3.進行類物件中的屬性初始化
四、關於抽象類我們需要注意:
1.抽象類一定不可以用final進行修飾,因為使用final的類不允許有子類。但是我們的抽象類是必須需要子類來實現抽象方法才可以進行例項化的。
2.抽象類也可以分為內部抽象類和外部抽象類。