眾所周之,在任何面向對象的語言中(包括Java、C#),在定義抽象類時必須使用abstract關鍵字。雖然這已經習已為常了,但實際上abstract是為了在實現接口或繼承抽象類避免歧議而必須存在的。
看如下代碼:
abstract class Class1
{
abstract void method();
}
上面的代碼是一個典型的抽象類,在定義類時和定義方法時都使用了abstract。但從編譯器的角度來說,在定義類時完全可以不使用abstract,如下面的代碼所示:
class Class1
{
abstract void method();
}
對於上面的代碼,編譯器在編譯時並不會產生奇異,只要檢測到類中有一個用abstract關鍵字的代碼,就可以在編譯的過程中自動向Class1添加abstract,也就是說,在定義Class1時添加abstract的工作應該由編譯器來完成。
雖然上面的過程看起來沒什麼問題,也並不難實現,但各位不要忘了,實現抽象類除了上面的方式,還有另外一種方式,這就是實現接口,而並不實現接口中的所有方法。看下面的代碼:
interface MyInterface
{
public void method1();
public void method2();
}
abstract class MyClass implements MyInterface
{
public void method1()
{
}
}
上面代碼中MyClass類並未實現method2方法,也並示在定義方法時使用abstract關鍵字,然後,method2方法實際上就是abstract方法。
大家可以想象,如果在定義抽象類時不使用abstract關鍵字會怎麼樣呢?看下面的代碼:
interface MyInterface
{
public void method1();
public void method2();
}
class MyClass implements MyInterface
{
public void method1()
{
}
}
上面的代碼一定會編譯出錯的,因為編譯器蒙了。在面向對象語言中規定,一個普通類必須實現接口中的所有方法。而在上面的代碼中,method2方法未實現。而編譯器無法判斷MyClass類是抽象類,還是普通類。如果按著普通類來處理,則會編譯出錯,如果按著抽象類來處理,則完全符合面向對象規則。因此,就產生了歧議。當編譯器在編譯源代碼時,一定會產生錯誤,否則可能會編譯成和源代碼的含義不同的二進制目標文件。
當然,上面的代碼也可以設置默認的規則,也就是按著普通類處理不通過時,就按著抽象類來處理。但這又會帶來另一個問題。如果開發人員忘記實現某個接口的方法,那不是這個類就會被編譯器認為是抽象類了嗎?因此,為了保險起見,編譯器的設計者特意為抽象類指定一個abstract關鍵字,也就是說,這個類是否是抽象類,應由開發人員通過編碼的方式來指定,而不是由編譯器自做主張。
從上面的描述可以看出,加abstract關鍵字主要是為了避免普通類在實現接口時產生的歧議。如果假設面向對象語言中沒有接口,abstract關鍵字完全可以去掉。當然,繼承抽象類也和實現接口類似。
象面向對象語言中的靜態方法很多就沒有靜態類的概念(Java沒有,C#有)。因此,在定義類時加不加static,並不會產生奇異,所以static關鍵字在定義靜態類時也就不是必須的了。
文章來源:http://www.cnblogs.com/nokiaguy/archive/2008/09/30/1302482.html