抽象類##
抽象類是用來描述抽象行為的贬芥,比如Animal笑诅,我們不知道Animal具體有會有什么樣的行為调缨,只有具體的動物類,如Dog吆你,Cat才有具體的行為弦叶,才能夠被實例化。抽象類是實現(xiàn)多態(tài)的一種機制早处,它可以包含具體方法(有具體實現(xiàn)的方法)湾蔓,也可以包含抽象方法,而繼承它的子類必須實現(xiàn)這些方法砌梆,下面總結了一下抽象類的特性:
- 抽象類不能被實例化默责,但可以有構造函數(shù)
- 抽象方法必須由子類進行重寫
- 只要包含一個抽象方法的類贬循,就必須定義為抽象類,不管是否還包含其他方法
- 抽象類中可以包含具體的方法桃序,也可以不包含抽象方法
- 抽象類可以包含普通成員變量杖虾,其訪問類型可以任意
- 抽象類也可以包含靜態(tài)成員變量,其訪問類型可以任意
- 子類中的抽象方法不能與父類的抽象方法同名
- abstract不能與private媒熊、static奇适、final或native并列修飾同一個方法
下面通過一個實例類來說明抽象類的使用
// 抽象類Animal,包含了一個抽象方法cry
abstract class Animal
{
public abstract void cry();
}
// 子類Dog繼承的抽象類Animal芦鳍,必須實現(xiàn)其抽象方法cry
class Dog extends Animal
{
public void cry()
{
System.out.println("Dog cry");
}
}
// 同樣嚷往,子類Cat繼承的抽象類Animal,必須實現(xiàn)其抽象方法cry
class Cat extends Animal
{
public void cry()
{
System.out.println("Cat cry");
}
}
public class Test
{
public static void main(String[] args) {
Animal a1 = new Dog(); // 抽象類引用指向子類實例
Animal a2 = new Cat();
a1.cry();
a2.cry();
}
}
輸出結果如下:
Dog cry
Cat cry
由輸出結果可以知道柠衅,使用a1,a2調用cry方法調用的是子類的cry方法皮仁,這是動態(tài)綁定,是實現(xiàn)多態(tài)的一種機制菲宴。
接口##
接口在Java當中是通過關鍵字interface
來實現(xiàn)贷祈,接口不是類,所以也不能被實例化喝峦,接口是用來建立類與類之間的協(xié)議势誊,它的提供的只是一種形式,而沒有具體的實現(xiàn)谣蠢。實現(xiàn)類實現(xiàn)(implements
)接口粟耻,必須實現(xiàn)接口的全部方法
接口是抽象類的延伸,Java不允許多重繼承(即不能有多個父類漩怎,只能有一個)勋颖,但可以實現(xiàn)多個接口。在使用接口的過程中勋锤,就注意以下幾個問題:
- 接口中不能有構造方法饭玲。
- 接口的所有方法自動被聲明為public,而且只能為
public
叁执,如果使用protected
茄厘、private
,會導致編譯錯誤谈宛。 - 接口可以定義"成員變量"次哈,而且會自動轉為
public final static
,即常量吆录,而且必須被顯式初始化窑滞。 - 接口中的所有方法都是抽象方法,不能包含實現(xiàn)的方法,也不能包含靜態(tài)方法
- 實現(xiàn)接口的非抽象類必須實現(xiàn)接口的所有方法哀卫,而抽象類不需要
- 不能使用
new
來實現(xiàn)化接口巨坊,但可以聲明一個接口變量,它必須引用一個實現(xiàn)該接口的類的對象此改,可以使用instanceOf來判斷一個類是否實現(xiàn)了某個接口趾撵,如if (object instanceOf ClassName){doSth()}
; - 在實現(xiàn)多接口的時候一定要注意方法名的重復
抽象類與接口的區(qū)別##
語法層次###
抽象類的定義,如下所示:
// 抽象類中可以包含抽象方法與非抽象方法(必須給出實現(xiàn))
public abstract class Demo
{
abstract void foo1();
void foo2(){
//實現(xiàn)
}
}
接口的定義共啃,如下所示:
interface Demo
{
// 接口中的方法自動轉為public abstract
void foo1();
void foo2();
}
抽象類方式中占调,抽象類可以擁有任意范圍的成員數(shù)據(jù),同時也可以擁有自己的非抽象方法移剪,但是接口方式中究珊,它僅能夠有靜態(tài)、不能修改的成員數(shù)據(jù)(即final static
挂滓,但是我們一般是不會在接口中使用成員數(shù)據(jù))苦银,同時它所有的方法都必須是抽象的。在某種程度上來說赶站,接口是抽象類的特殊化。
設計層次###
從設計的層面來看纺念,我覺得抽象類與接口有如下幾個不同點:
- 抽象層次不同贝椿。可以這樣理解陷谱,抽象類是對類的抽象烙博,接口是對行為的抽象。抽象類對是類整體進行抽象烟逊,包括屬性渣窜、行為,而接口是對類局部(行為)進行抽象宪躯。
- 跨域不同乔宿。抽象類所跨域的是具有相似特點的類,而接口可以跨域不同的類访雪。抽象類所體現(xiàn)的是一種繼承關系详瑞,要想使得繼承關系合理,父類和派生類之間必須存在"is-a" 關系臣缀,即父類和派生類在概念本質上應該是相同的坝橡。對于接口則不然,并不要求接口的實現(xiàn)者和接口定義在概念本質上是一致的精置, 僅僅是實現(xiàn)了接口定義的契約而已计寇。
總結##
- 抽象類在java語言中所表示的是一種繼承關系,一個子類只能存在一個父類也颤,但是可以存在多個接口颅和。
- 在抽象類中可以擁有自己的成員變量和非抽象類方法,但是接口中只能存在靜態(tài)的不可變的成員數(shù)據(jù)(不過一般都不在接口中定義成員數(shù)據(jù))或详,而且它的所有方法都是抽象的贝淤。
- 抽象類和接口所反映的設計理念是不同的柒竞,抽象類所代表的是"is-a"的關系,而接口所代表的是"like-a"的關系播聪。抽象類和接口是java語言中兩種不同的抽象概念朽基,他們的存在對多態(tài)提供了非常好的支持,雖然他們之間存在很大的相似性离陶。但是對于他們的選擇往往反應了您對問題域的理解稼虎。只有對問題域的本質有良好的理解,才能做出正確招刨、合理的設計霎俩。