1. 程式人生 > >《 Thinking in Java 》第九章 介面

《 Thinking in Java 》第九章 介面

介面和內部類為我們提供了一種將介面與實現分離的更加結構化的方式

抽象類和抽象方法

抽象方法:僅有宣告而沒有方法體。 下面是抽象方法語法:

abstract void f();

包含抽象方法的類叫做抽象類。如果一個類包含一個或多個抽象方法,該類必須被限定為抽象的。

如果想從一個抽象類繼承,並想建立該心累的物件,就必須為基類中的所有抽象方法提供方法定義。如果不這樣做,那麼匯出類也是抽象類,編譯器會強制要求用 abstract 關鍵字來限定這個類。

介面

abstract 允許在類中建立一個或多個沒有定義的方法——提供了介面部分,但是沒有提供任何相應的具體實現。 interface 產生一個完全抽象

的類,它根本就沒有提供任何具體的實現。 如果不新增 public 關鍵字,它只具有包訪問許可權,介面也可以包含域,但是這些域隱式地是 staticfinal 。 在介面中被定義的方法必須被定義是 public 的,在沒有宣告時,自動就是 public 。

Java 中的多重繼承

繼承多個介面,並可以向上轉型為每個介面,因為每一個介面都是一個獨立型別。

通過繼承來擴充套件介面

一個介面可以擴充套件另一個或多個介面,從而輕易地做到為介面新增新的宣告方法。

組合介面時的名字衝突

interface I1 { void f(); }
interface I2 { int f(int f); }
interface
I3 { int f(); } class C { public int f() { return 1; } } class C2 implements I1, I2 { @Override public void f() { } @Override public int f(int i) { return 1; } } class C3 extends C implements I2 { @Override public int f(int i) { return 1; } } class C4 extends C implements I3
{ public int f() { return 1; } } //class C5 extends C implements I1 {} //interface I4 extends C implements I1 {}

最後兩行為錯誤的,因為過載、重寫和實現混雜在一起,具體參照之前章節過載的規則問題,即可發現錯誤所在。

介面中的域

放入介面中的任何域都自動是 static 和 final 的。

初始化介面中的域

在介面中的域不能是 “空白 final ”,但是可以被非常量表達式初始化。 因為域是 static 的,他們在第一次被載入時初始化,發生在任何域首次被訪問時。 當然這些域不是介面的一部分,他們的值被儲存在該介面的靜態儲存區域內。

巢狀介面

介面可以巢狀在類或其他介面中。

class A {
	interface B {
		void f();
	}
	public class BImpl implements B {
		public void f() {
		}
	}
	private class BImpl2 implements B {
		public void f() {
		}
	}
	
	
	//********************
	
	public interface C {
		void f();
	}
	class CImpl implements C {
		public void f() {
		}
		
	}
	private class CImpl2 implements C {
		public void f() {
		}
		
	}
	
	//**************************
	private interface D {
		void f();
	}
	private class DImpl implements D {
		public void f() {
		};
	}
	public class DImpl2 implements D {
		public void f() {
			
		}
	}
	
	public D getD() {
		return new DImpl2();
	}
	private D dRef;
	public void receiveD(D d) {
		dRef =  d;
		dRef.f();
		
	}
	
	
	interface E {
		interface G{
			void f();
		}
		public interface H {
			void f();
		}
		void g();
	}
	
}

public class NestingInterfaces {
	public class BImp implements A.B {
		public void f() {
		}
	}
	class CImp implements A.C {
		public void f() {
		}
	}
	class EImp implements E {
		public void g() {
		}
	}
	class EGImp implements E.G {
		public void f() {
		}
	}
	class EImp2 implements E {
		public void g() {
		}
		class EG implements E.G{
			public void f() {
			}
		}
	}
	
	public static void main(String[] args) {
		A a = new A();
		// Can't access A.D:
		//! A.D ad = a.getD();
		//Doesn't return anything but A.D:
		//! A.DImp2 di2 = a.getD();
		//Only anoter A can do anythig with getD();
		A a2  = new A();
		a2.receiveD(a.getD());
	}
}

在類中巢狀介面的語法是顯而易見的,可以有 public 和“包訪問”兩種可視性。 作為一種新新增的方式,介面也可以被實現為 private 的,就像在 A.D 中所看到的(相同的語法既適用於巢狀介面,也適用於巢狀類)。 private 介面能夠被實現為 DImp 中的一個 private 內部類,也可以實現為 public 類,如 A.DImp2 。但是 A.DImp2 只能被其自身使用。

實現一個 private 介面只是一種方式,它可以強制該介面中的方法定義不要新增任何型別資訊(也就是說,不允許向上轉型)。

getD() 方法可以看到用 public 方法返回了 private 的介面。顯然,在除 A 物件的其他地方,是看不到 這個 D private 介面的,所以只能使用 A 這個本身有許可權的物件的某個類似於 receiveD() 方法來使用。 介面 E 說明介面之間也可以巢狀,因此,巢狀在另一個介面中的介面自動就是 public 的,而不能宣告為 private 的。