1. 程式人生 > >java面向物件——抽象類與介面

java面向物件——抽象類與介面

1. 抽象類

抽象類就是指具有抽象方法並且使用abstract關鍵字修飾的類。

抽象類不能例項化物件,否則編譯出錯
抽象類中可以有成員變數,成員方法以及構造方法
抽象類中可以有抽象方法也可以沒有,但定義了抽象方法就必須是抽象類

抽象類的作用

抽象類的意義不在於例項化物件而在於被繼承,因為子類若不重寫抽象類中的抽象方法,則子類也要變成抽象類,因此抽象類對子類具有強制性和規範性。

抽象類為其子類“抽象”出了公共的部分,通常也定義了子類所必須具體實現的抽象方法。

因此使用抽象類的設計通常叫做模板設計模式。

經驗: 在以後的開發中推薦使用父類的引用指向子類物件的形式,因為這種情況下引用直接呼叫的方法一定是父類擁有的方法,此時若更改指向的子類物件,那麼後續直接呼叫的方法不需要做任何的修改直接生效,因此提供了程式碼的可維護性。

【抽象方法】

抽象方法就是指不能有具體實現的方法,僅僅有方法的定義,而沒有方法體,通常使用abstract關鍵字修飾

訪問控制符 abstract 返回值型別 方法名(形參列表)
public abstract void cry();

抽象類是不能構造物件的但可以有構造方法,為什麼?

解析:抽象類中通常有抽象方法,而抽象方法的呼叫是沒有意義,
      抽象類不能構造物件的原因就是為了避免呼叫抽象方法。

【經典題型】

自定義狗類,屬性有:名字、重量,牙齒數量,行為有:吃食物、看家。 自定義貓類,屬性有:名字、重量、顏色,行為有:吃食物、抓老鼠。 自定義抽象動物類描述狗類和貓類的相同成員,其中吃食物設計為抽象方法。 自定義測試類,包含一個main方法,在main方法中使用多型的語法去呼叫各個方法。

//以下程式碼省略 getXX 和 setXX 方法

public abstract class Pet {
	private String name;
	private double weight;
	
	public Pet() {			 //無參構造方法
		super();			//表示呼叫父類中的無參構造方法,預設父類是java.lang.Object類。
	}
	public Pet(String name, double weight) {
		super();
		this.name = name;
		this.weight = weight;
	}
		
	public abstract void eat();		//【抽象方法】僅有方法的定義,而沒有方法體,
								  //通常使用abstract關鍵字修飾,用於繼承使用

	public void show(){				//用以方法重寫
		System.out.println("我叫:"+name+",體重是"+weight+"千克。");
	}
}


public class Pet_Dog extends Pet{
	private int tooth;
	
	public Pet_Dog() {		 //無參構造
		super();			//繼承於Pet類
	}
	public Pet_Dog(String name,double weight,int tooth) {
		super(name,weight);			//呼叫父類的建構函式,並向父類的建構函式傳參進行初始化
		this.tooth = tooth;			//初始化tooth
	}
	
	public int getTooth() {			
		return tooth;
	}
	public void setTooth(int tooth) {
		this.tooth = tooth;
	}
	@Override		//標註:【方法重寫】的識別符號,告訴編譯器下面的方法是對【父類中方法】的重寫版本
	public void eat() {
		System.out.println("狗吃肉");
	}
	public void show(){			 //方法過載
		super.show();			//呼叫父類的show方法
		System.out.println("我有"+tooth+"顆牙!");
	}
	public void action(){
		System.out.println("我會看家");
	}
}


public class Pet_Cat extends Pet {
	private String color;
	
	public Pet_Cat() {
		super();
	}
	public Pet_Cat(String name,double weight,String color) {
		super(name,weight);
		this.color = color;
	}

	@Override
	public void eat() {
		System.out.println("貓吃魚");
	}
	public void show(){
		super.show();
		System.out.println("我有一身"+color+"顏色的毛!");
	}
	public void action(){
		System.out.println("貓貓抓老鼠");
	}
}


public class Pet_Test {
	public static void method(Pet x){
		//在編譯階段呼叫Shape型別的show()方法,在執行階段呼叫Rect型別的show()方法
		//在編譯階段呼叫Shape型別的show()方法,在執行階段呼叫Circle型別的show()方法
		x.show();
		x.eat();
		if(x instanceof Pet_Dog){
			((Pet_Dog) x).action();
		}
		else{
			((Pet_Cat) x).action();
		}
	}
	public static void main(String[] args){
		Pet p1 = new Pet_Dog("汪汪",10,30);
		Pet p2 = new Pet_Cat("喵喵",5,"白");
		Pet_Test.method(p1);
		System.out.println("--------------------");
		Pet_Test.method(p2);
	}
}

2. 介面

【介面】可以看成是特殊的抽象類。即為只可包含常量和抽象方法的抽象類。體現在連構造方法都沒有

一個實現可以有多個介面,彌補了一個子類只可有一個父類的限制。【通俗的講就是一個兒子有多個爹】

定義類的關鍵字是class,定義介面的關鍵字是interface

繼承類的關鍵字是extends,實現介面的關鍵字是implements

介面中的所有變數都必須由public static final 共同修飾(即只能定義常量,所有字母大寫)

介面中所有方法都必須由public abstract 共同修飾,可以省略但推薦寫上

定義介面
------------------------------------------------------------------------------
public interface Runner {					//通過interface關鍵字定義介面
	public static final int DEF_SPEED = 100;	//介面中不可以定義成員變數,但可以定義常量
	public abstract void run();		//介面中只可以定義沒有實現的方法(可以省略 public abstract)
}
------------------------------------------------------------------------------
介面的實現
class AmericanCurl implements Runner,man...{	//與繼承不同,一個類可以實現多個介面,實現的介面直接										    //用逗號分隔。當然,該類需要實現這些介面中定義的所有方法
  	public void run(){
      	System.out.println("run...");		//一個類可以通過implements關鍵字”實現”介面。一個類實現										   //了某個介面後必須實現該介面中定義的所有方法
  	}
}

Runner runner = new AmericanCurl();			//介面可以作為一種型別宣告變數,一個介面型別的變數可以
										 //引用實現了該介面的類的物件;通過該變數可以呼叫該介面中										   //定義的方法(具體的實現類提供了方法的實現)。

例子

public interface Metal {
	public abstract void shine();	//在金屬介面中自定義方法描述發光的行為
}
------------------------------------------------
public interface Money {
	public abstract void buy();		//在貨幣介面中自定義buy()方法來模擬買東西的行為
}
------------------------------------------------
public class Gold implements Money, Metal {

	@Override
	public void buy() {
		System.out.println("買了好多好吃的...");
	}
	@Override
	public void shine() {
		System.out.println("發出了金黃色的光芒...");
	}

	public static void main(String[] args) {
		Money mn = new Gold();			//介面型別的引用指向了實現類的物件,形成了多型
		mn.buy();
		Metal mt = new Gold();			//介面型別的引用指向了實現類的物件,形成了多型
		mt.shine();
	}
}

類和介面之間的關係

  型別    	      關鍵字      	   方式    

類和類之間的關係 使用extends關鍵字 支援單繼承 類和介面之間的關係 使用implements關鍵字 支援多實現 介面和介面之間的關係 使用extends關鍵字 支援單繼承/多實現

介面的繼承

介面之間可以存在繼承關係,一個介面可以通過extends關鍵字繼承另一個介面,子介面繼承了父介面中定義的所有方法。

抽象類和介面之間的主要區別(筆試題)

  1. 定義抽象類的關鍵字是class,定義介面的關鍵字是interface。
  2. 繼承抽象類的關鍵字是extends,而實現介面的關鍵字是implements。
  3. 繼承抽象類是單繼承,而實現介面是多實現。
  4. 抽象類中有構造方法,而介面中沒有。
  5. 抽象類中可以有成員變數,而介面中只有常量。
  6. 抽象類中可以有成員方法,而介面中只有抽象方法。
  7. 抽象類中增加方法可以不影響子類,但介面一定影響子類。