java語言,聲明類時格式為: abstract class Db{} 説明Db類為抽象類。抽象方法是説沒有方法的實現(方法體)此方法為抽象方法,只有抽象類和接口中才可以有抽象方法。簡而言之,含有抽象方法的類一定是抽象類;關鍵字是abstract
抽象類本質
1.從類的組成上看其是抽象方法和非抽象方法的集合,還有屬性(常量)。
2.從設計的角度來看,實際上抽象類定義了一套規範(抽象方法)。(規範)
使用規則
- 抽象類必須被繼承,抽象方法必須被重寫。
- 抽象類中的抽象方法只需聲明,無需實現,沒有方法體;
- 抽象類不能被實例化,抽象類不一定要包含抽象方法,而定義抽象方法的類必須是抽象類。
- 抽象類包含的抽象方法必須在其子類中被實現,否則該子類也必須是抽象類。
- 抽象類可以有構造方法供子類實例化對象
- 抽象類不能直接實例化使用,一般用的是抽象類的子類,
A a = new B();
A和B之間的關係,繼承關係,接口實例關係。
下面逐條解釋:
規則一
抽象類必須被繼承,抽象方法必須被重寫。
規則二
抽象類中的抽象方法只需聲明,無需實現,沒有方法體。
在Java中抽象類實際上是一種規範,一般在抽象類中聲明方法不直接提供方法體(當然也可以提供),而是通過其子類去重寫其抽象方法:
package day_12_01.abs;
/**
* @author soberw
*/
public abstract class A {
//報錯,不能定義抽象屬性
// abstract int a;
//可以聲明屬性
private int a;
//可以聲明一個普通方法
public void a(){
}
//報錯,因為抽象方法不能有方法體,即不能去實現
// public abstract void aa(){
//
// }
//抽象方法正確格式
public abstract void aa();
//抽象方法不能是私有的private
// private abstract void bb();
}
//沒有重寫父類的抽象方法aa(),報錯
//class B extends A{
//
//}
注意
抽象方法不能是私有的private,因為一旦私有,子類就不能重寫了,但這違背了抽象方法必須被重寫的原則。
規則三
抽象類不能被實例化,抽象類不一定要包含抽象方法,而定義抽象方法的類必須是抽象類。
首先,抽象類不能被實例化,當一個類實例化對象後,這個對象就可以調用類中的屬性或者方法了,但在抽象類有抽象方法(沒有方法體),無法調用。自相矛盾,所以無法實例化。比如,我想實例化上例中的抽象類A:
class TestA{
public static void main(String[] args) {
//報錯
// A a = new A();
}
}
抽象類不一定有抽象方法,這點顯而易見,但是意義不大:
//一個空的抽象類
abstract class AA{
}
然後,定義抽象方法的類必須是抽象類,這點也很好理解,一個普通的類是可以被實例化的,如果這個普通類存在抽象方法,那我是不是就可以通過對象去調用呢?當然不能。
package day_12_01.abs;
/**
* @author soberw
*/
//報錯,因為抽象方法必須聲明在抽象類中
//public class B {
// public abstract void b();
//}
規則四
抽象類包含的抽象方法必須在其子類中被實現,否則該子類也必須是抽象類。
還拿上述代碼做例子,如果我聲明瞭一個類B,繼承於A,那B就必須重寫A中的抽象方法,否則報錯(因為普通類中不能有抽象方法),解決方式一:重寫父類抽象方法;解決方式二:將B聲明為abstract:
//解決方式一:重寫父類抽象方法
class B extends A{
@Override
public void aa() {
}
}
//解決方式二:將B聲明為abstract
abstract class Bb extends A{
}
規則五
抽象類可以有構造方法供子類實例化對象。
這點很好理解,因為首先可以確定的是,Java中所有的類都有構造方法,即使你是抽象類,雖然我們沒寫,但其實系統已經默認給我們提供了一個無參的空構造器,例如下面我顯示化的在抽象類中聲明一個構造方法:
package day_12_01.abs;
/**
* @author soberw
*/
public abstract class Ab {
public Ab(){
System.out.println("Abs......");
}
}
class Abs extends Ab{
}
class Test{
public static void main(String[] args) {
Abs abs = new Abs();
}
}
運行結果:
證明我們在創建子類實例化對象時,父類的構造器也可實現(哪怕父類是抽象類)
規則六
抽象類不能直接實例化使用,一般用的是抽象類的子類。
抽象類不能去實例化對象,那如果我想用其中的一些非抽象方法呢,比如靜態方法,比如普通方法呢或者是屬性?
我們可以通過繼承關係,去創建其子類的對象,形如:
A a = new B(); //其中A是父類,B是子類
package day_12_01.abs;
/**
* @author soberw
*/
public abstract class TT {
String some = "hello";
public static void talk() {
System.out.println("talk...");
}
public void say() {
System.out.println("say..." + some);
}
}
class FF extends TT{
}
class FFTest{
public static void main(String[] args) {
TT.talk();
TT f = new FF();
f.say();
}
}
運行結果:
如果子類重寫了父類的非抽象方法,那實際調用的就是子類重寫後的。通過子類去調用父類的方法,即通過父類去new一個子類的對象,這實際上也是多態性的一種體現。當然了,抽象類中的靜態方法是可以直接調用的(除非是私有的),實際上對任何類都一樣。