一、抽象類
1、抽象方法
抽象方法只有聲明,而沒有具體的實現(xiàn)。也就是說沒有{}。
抽象方法的聲明格式為:abstract void 方法名();
2、抽象類
包含一個抽象方法的類就是抽象類 使用abstract類就是抽象類
3、特點
1.抽象類與抽象方法必須使用abstract修飾
2.抽象類不允許創(chuàng)建對象
3.抽象類總可以有抽象方法也可以沒有抽象方法.如果抽象類中有帶主體方法子類繼承也可以直直接用
4.抽象類的子類使用
??? a.繼承抽象類,重寫抽象方法
??? b.抽象類的子類也可是抽象類
4.格式
public?abstract?class?People {?//關(guān)鍵詞abstract,聲明該類為抽象類
?????? public?int?age;
?????? public?void?Num() {
?????? }
?????? public?abstract?Name();?//聲明該方法為抽象方法
}
注意:
abstract不能與final并列修飾同一個類
abstract 不能與private、static、final或native并列修飾同一個方法。
5.使用
在下面這個例子中,把打印機類封裝成抽象類,把print定義成抽象類,當HPPrinter和CannonPrinter要繼承printer類的時候,必須重寫print函數(shù)。這樣寫的好處是,每個打印機都有自己打印方式,此舉可以防止子類沒有寫明打印方式。
public?abstract?void?Printer() {
?????? public?void?open() {
??????????? system.out.print("打印機開啟");
??????? }
??????? public?void close() {
??????????? system.out.print("打印機關(guān)閉");
??????? }
??????? abstract?void?print();?//把print方法定義為抽象方法
? }
public?HPPrinter?extends?Printer {
???????? void?print(){?//必須重寫抽象方法print()??
??????????????? system.out.print("惠普打印機開始打印");
????????? };
}
public?CanonPrinter?extends?Printer {
???? void?print(){?//必須重寫抽象方法print()
????????????? system.out.print("佳能打印機開始打印");
????? };
}
接口
接口可以理解為一種特殊的類,里面全部是由全局常量和公共的抽象方法組成
1.格式
public interface?interface 接口名稱{
? ? ? 全局常量
? ? ? 抽象方法
}
2.特點
1.使用關(guān)鍵字interface
2.接口的實現(xiàn)也必須通過子類,使用關(guān)鍵字implements,而且接口是可以多實現(xiàn)的
class?A?implements?Inter1,Inter2{?//Inter1和Inter2是接口???
?? ...
}
3.一個類可以同時繼承抽象類和接口
class?A?extends?Abs?implements?Inter1,Inter2{?//Abs是一個抽象類???
??? ...
}
4.一個接口不能繼承普通的類,但可以通過extends關(guān)鍵字繼承多個接口,實現(xiàn)接口的多繼承
interface?Inter?extends?Inter1,Inter2{?//Inter、Inter1、Inter2都為接口??
? ?? ...
}
5.接口中可以含有 變量和方法。但是要注意,接口中的變量會被隱式地指定為public static final變量(并且只能是public static final變量,用private修飾會報編譯錯誤),而方法會被隱式地指定為public abstract方法且只能是public abstract方法(用其他關(guān)鍵字,比如private、protected、static、 final等修飾會報編譯錯誤)
6.無構(gòu)造方法
抽象類和接口的區(qū)別

一、語義層次
public?abstract?class?People {?//關(guān)鍵詞abstract,聲明該類為抽象類
????? void?Num();
????? abstract?void?Name(); //聲明該方法為抽象方法
}
Interface Person {
?????? void?Num();
?????? void?Name();
}
一、抽象類方式中,抽象類可以擁有任意范圍的成員數(shù)據(jù),同時也可以擁有自己的非抽象方法,但是接口方式中,它僅能夠有靜態(tài)、不能修改的成員數(shù)據(jù)(但是我們一般是不會在接口中使用成員數(shù)據(jù)),同時它所有的方法都必須是抽象的。
二、在某種程度上來說,接口是抽象類的特殊化。
三、對子類而言,它只能繼承一個抽象類(這是java為了數(shù)據(jù)安全而考慮的),但是卻可以實現(xiàn)多個接口。
二、設(shè)計層次
1、 抽象層次不同
抽象類是對類抽象,而接口是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為,但是接口卻是對類局部(行為)進行抽象。
2、 跨域不同
抽象類所跨域的是具有相似特點的類,而接口卻可以跨域不同的類。我們知道抽象類是從子類中發(fā)現(xiàn)公共部分,然后泛化成抽象類,子類繼承該父類即可,但是接口不同。實現(xiàn)它的子類可以不存在任何關(guān)系,共同之處。例如貓、狗可以抽象成一個動物類抽象類,具備叫的方法。鳥、飛機可以實現(xiàn)飛Fly接口,具備飛的行為,這里我們總不能將鳥、飛機共用一個父類吧!所以說抽象類所體現(xiàn)的是一種繼承關(guān)系,要想使得繼承關(guān)系合理,父類和派生類之間必須存在"is-a" 關(guān)系,即父類和派生類在概念本質(zhì)上應(yīng)該是相同的。對于接口則不然,并不要求接口的實現(xiàn)者和接口定義在概念本質(zhì)上是一致的, 僅僅是實現(xiàn)了接口定義的契約而已。
3、 設(shè)計層次不同
對于抽象類而言,它是自下而上來設(shè)計的,我們要先知道子類才能抽象出父類,而接口則不同,它根本就不需要知道子類的存在,只需要定義一個規(guī)則即可,至于什么子類、什么時候怎么實現(xiàn)它一概不知。比如我們只有一個貓類在這里,如果你這是就抽象成一個動物類,是不是設(shè)計有點兒過度?我們起碼要有兩個動物類,貓、狗在這里,我們在抽象他們的共同點形成動物抽象類吧!所以說抽象類往往都是通過重構(gòu)而來的!但是接口就不同,比如說飛,我們根本就不知道會有什么東西來實現(xiàn)這個飛接口,怎么實現(xiàn)也不得而知,我們要做的就是事前定義好飛的行為接口。所以說抽象類是自底向上抽象而來的,接口是自頂向下設(shè)計出來的。
實例:
現(xiàn)在有個鳥類,鳥的屬性有種類,顏色,重量等,鳥的行為有吃,飛。但是有的鳥類只會奔跑不會飛(鴕鳥)。這時如果我們在一個Birds類中去定義飛和奔跑的行為,分別讓只會飛的鳥和只會奔跑的鳥都去繼承這個類,好像有些不太妥當。我們可以這樣解決:定義一個抽象類,屬性包括種類、顏色、重量,行為包括吃。在定義一個Fly接口,包含一個方法fly()。在定義一個Run接口,包含一個run()方法。如果只是會飛的鳥我們就繼承Birds類,實現(xiàn)Fly接口。如果只是會奔跑的鳥我們就實現(xiàn)Birds類,實現(xiàn)Run接口。如果繼承Birds類,實現(xiàn)了Fly和Run接口,那就是又會飛又會奔跑的鳥。實現(xiàn)代碼如下:
定義鳥的抽象類其中用3個成員變量一個eat的抽象方法,一個print方法
public?abstract?class?Birds?{?
???????? private?String?type;?
???????? private?String?color;?
???????? private?double?weight;????????? public?Birds(String?type,?String?color,?double?weight){?
??????????????? this.setType(type);?
?????????????? this.setColor(color);?
?????????????? this.setWeight(weight);?
? ? ? ? ?? }????????? public?abstract?void?eat();
???????? public?void?print(){?
????????????? System.out.println("種類:"+this.getType());?
????????????? System.out.println("顏色:"+this.getColor());?
????????????? System.out.println("重量:"+this.getWeight());?
? ? ? ? }?????? public?String?getType()?{?
???????? ? ? return?type;?
?? ? ? }
? ? ? public?void?setType(String?type)?{?
????? ?? ?? this.type?=?type;
? ? ?? }?
????? public?String?getColor()?{?
????????? return?color;?
?????? }?
?????? public?void?setColor(String?color)?{?
????????? this.color?=?color;?
? ? ?? }?
???? public?double?getWeight()?{?
??????? return?weight;?
???? }?
??? public?void?setWeight(double?weight)?{?
??????? this.weight?=?weight;?
??? }?
}
定義飛的接口
public?interface?Fly?{?
??? void?fly();?
}?
定義跑的接口
public?interface?Run?{?
??? void?run();?
}?
/**
*?蜂鳥 繼承抽象類,實現(xiàn)Fly的接口
*/?
public?class?HummingBird?extends?Birds?implements?Fly?{
???? public?HummingBird(String?type,?String?color,?double?weight){?
???????? super(type,?color,?weight);?
???? }??? @Override?
??? public?void?fly()?{
??????? //實現(xiàn)飛接口中的方法
??????? System.out.println("我是"+this.getType()+",我會fly。");?
??? }??? @Override?
?? public?void?eat()?{
?? //實現(xiàn)抽象類中的抽象方法
? ? System.out.print("我是"+this.getType()+",我吃花蜜。");?
?? }?
}?
/**
*?鴕鳥
*/??public?class?OstrichBirds?extends?Birds?implements?Run?{
?????? public?OstrichBirds(String?type,?String?color,?double?weight)?{?
?????????? super(type,?color,?weight);?
? ? ? ? }????? @Override
?????? public?void?run()?{?
?????? System.out.println("我是"+this.getType()+",我會奔跑。");?
?????? }? ???????? @Override?
?????? public?void?eat()?{?
?????? System.out.println("我是"+this.getType()+",我吃草。");?
????? }?
}?
public?class?Test?{?
???? public?static?void?main(String?[]?args){?
????????? //蜂鳥?
???????? Birds?hummingBirds?=new?HummingBird("蜂鳥",?"彩虹色",?2.3);?
? ? ? ?? hummingBirds.print();?
???????? hummingBirds.eat();?
???????? Fly?f?=?(Fly)?hummingBirds;?
???????? f.fly();???????? //鴕鳥?
??????? OstrichBirds?ostrichBirds?=new?OstrichBirds("鴕鳥",?"灰色",?200.2);?
??????? ostrichBirds.print();?
??????? ostrichBirds.eat();?
??????? ostrichBirds.run();???????? System.out.println("是否會飛=>"+(hummingBirds?instanceof?Fly));?
??????? }
}?