今天來補充說明抽象類和接口。
對於class定義,格式如下:
[public|protected|private] [abstract|final] class 類名
{
//類的內容
....
}
前面是modifIEr。
需要特別說明的是,對於一個JAVA文件,要求裡面一定只能有一個和該文件同名的public類。但是倒不是說一個Java文件只能有一個類:
Java代碼
//file name: ClassDeinfeDemo.Java
package classdefine;
/**
* This class is required in this file
*/
public class ClassDeinfeDemo
{
}
public class AnotherPublicClass
{
}
class ProtectedClass
{
}
像上面的寫法也是可以的,只是一般情況下我們不提倡。因為一般這樣寫的原因只有一個,就是這個類只會在同一個Java文件裡面被調用,而不會在其它地方被調用。而且這種寫法只能定義default類型的普通類,抽象類,或者final類
另外類中有類也是可以的:
Java代碼
package classdefine;
public class MemberClassDemo
{
/**
* I'm a member of this class
*/
private class MemberClass
{
}
public class PublicMemberClass
{
}
}
private類型的類只能通過這種方式來定義。
需要注意的是,成員類的外部調用是很有趣的:
Java代碼
package classdefine;
public class MemberClassCall
{
public static void main(String[] args)
{
new MemberClassDemo.PublicMemberClass();
}
}
只要把成員類的所有類也加進來,然後用.來調用成員類就好了。這種調用方式和static方法的調用是一樣的
然後就是抽象類的定義:
Java代碼
package classdeinfe;
public abstract AbstractClass
{
public abstract void abstractMethod();
public void entityMethod()
{
....
}
}
和一般的類不一樣,abstract類裡面可以定義抽象方法。抽象方法不需要實現,這點和一會介紹的接口類似。
但是和接口不一樣的地方,就是抽象類裡面也可以定義具體的方法體。抽象類的一般用法就是定義一類類的普遍行為,然後預言其中實現各部相同但是卻共有的方法,例如:
Java代碼
package classdeinfe;
public abstract Vehicle
{
public abstract float speed();
public void run()
{
....
}
public void stop()
{
....
}
public boolean isMoving()
{
....
}
}
上例列出了一個交通工具抽象類,各類都會有run,stop,isMoving和speed方法。而且stop,run和isMoving方法行為默認都是一樣的,而speed則留待子類去實現。當我們每個子類都預期會實現父類某個特定方法的時候,建議把這個父類方法定義為一個抽象方法。這樣可以強迫子類針對該方法去定義各自的行為。
假如我們在類定義的時候,使用了final關鍵字,則該類不允許再被繼承:
Java代碼
package classdefine;
public final class FinalClass
{
}
最後我們說一下接口。接口的定義和類類似:
Java代碼
package classdeinfe;
public interface MyInterface
{
public static final String CONSTANT_DEMO = "test";
public void publicMethod();
void defaultMethod() throws Exception;
接口類專門用於定義一系列的方法,及相應的一些配套常量。現在我們就多了一種指針——接口指針。首先看看以下例子:
Java代碼
package classdeinfe
public class MyInterfaceImpl implements MyInterface{
public void publiMethod()
{
....
}
/**
* 盡管我們的接口定義的方法訪問控制類型為默認,但是實現類裡面
* 這個方法一定要是共有的
*/
public void defaultMethod() throws Exception
{
....
}
}
首先,實現接口的類用implements關鍵字表達,而且接口的實現和繼承不一樣,一個類可以實現多個接口,各接口用,分開就可以。但是要注意不要有兩個接口的方法名一致而返回類型不一致。對於所有的接口方法的實現,都必須是標識為共有訪問權。
可能大家會問接口方法標為公有和默認有什麼區別呢?很簡單,就是當你是調用接口指針變量去訪問方法時,會有不同:
Java代碼
package classdeinfe.sub;
import classdeinfe.MyInterface;
import classdeinfe.MyInterfaceImpl;
public class InterfaceCallDemo1
{
public static void main(String[] args)
{
MyInterface intf = new MyInterfaceImpl();
intf.publicMethod(); //可以調用
intf.defaultMethod(); //無法調用,因為是default方法
/*
* 可以調用,因為對於MyInterfaceImpl類來說,其defaultMethod是
* 公有方法
*/
((MyInterfaceImpl)intf).defaultMethod();
}
}
上面是一個很有趣的例子。它同時為我們展現了接口指針的用法,也告訴我們在指針裡面定義默認方法和公有方法的區別。
那麼,可能大家想知道,接口類有什麼用途呢?如果大家要做架構分離,還有單元測試,就會知道接口定義是非常方便的一種設計模式。
因為接口指針可以幫助我們把實現類和調用類分離,當然我們上面的例子不足以說明這個好處。這種做法的實現方式以前我們一般會采用大工廠方式,就是在一個類裡面,定義出所有接口及其調用實現類的匹配關系,然後提供一個getInstance方法,給出特定接口類,獲取對應的接口實現,但是這個實現會對調用getInstance的類透明,它只拿到一個可以被調用接口方法的實現而已,而不是直接去調用這個實現實體。
試想一下,我們對數據庫的操作,全部用接口模式實現的話,那麼即使我更換了數據庫,最壞的情況也就是把所有數據庫操作的實現類代碼重寫就可以了,而不需要連調用數據庫操作層的代碼也要修改。這就是接口提供的便利。因為它為我們的代碼分離提供了可能。
現在接口這種設計模式,隨著Spring及IoC概念的普及,已經得到大家的普遍認可。而且,我們還發現,這種模式還能夠讓單元測試更加簡單。因為不同層次的邏輯分離,使得單元測試的獨立性更加容易實現。
要注意的是,對於實現接口的類來說,其實現接口也算是父類哦。。。。。。