Java面向对象(3) —— 抽象类、接口、内部类、匿名内部类
目錄
- 抽象類(abstract)
- 抽象類的使用方法
- 抽象類的應用:模板方法模式
- 接口
- 接口的概念
- 接口的特點
- 接口的使用
- 接口實現與抽象類繼承的區別
- 接口的多繼承
- 內部類
- 概念
- 成員內部類(使用較多)及應用
- 創建成員內部類的實例
- 在成員內部類中訪問外部類的成員方法和屬性
- 外部類不能直接訪問內部類的成員,必須先建立內部類的對象才能訪問
- 成員內部類有以下限制
- 匿名內部類
- 概念
- 匿名內部類的創建與訪問
抽象類(abstract)
java中可以定義沒有方法體(只有方法頭)的方法,該方法由子類來具體實現。該沒有方法體的方法我們稱之為抽象方法,含有抽象方法的類我們稱之為抽象類。
有抽象方法的類,一定是抽象類。即抽象方法只能放在抽象類中。
但是抽象類中可以有具體方法,可以沒有抽象方法。
特點:
(1)抽象方法不能被調用
抽象方法代表一種不確定的操作或行為
(2)抽象類不能被實例化
雖然按照提示也能完成方法體實例化,但這是不靠譜的使用方式(這種不靠譜的方式也是后面提及的匿名的內部類)
(3)抽象方法用abstract來修飾
不可以被實例化,那怎么使用這個抽象類呢?
抽象類的使用方法
做一個類來繼承這個抽象類,繼承的時候把方法體實現了,如下:
//抽象方法只能放到抽象類里面,因此前面也要加abstract abstract class Test1 {abstract void printInfo(); //在抽象類里面的方法,要么完善方法體,要么作為抽象方法 } //沒有方法體的方法,該方法由子類來具體實現//類似C語言中對函數的聲明class Test2 extends Test1 //繼承抽象類,從而使用抽象類 {@Overridepublic void printInfo() {System.out.println("來自:test2");} }public class Demo1 {public static void main(String[] args){Test2 t2 = new Test2();t2.printInfo();} }抽象類的應用:模板方法模式
模板方法模式定義:
父類抽象(abstract)化定義一系列方法作為模板(不具體),把一些步驟推遲到子類去實現,子類將重寫這些方法以提供具體行為。
之前做的智能家居可以運行在多個平臺上,比如51,32,樹莓派,現在就定義在每個平臺上完成這個項目的通用模板,然后再在具體平臺實現,以51為例子(當然這只是一個類比,java在51單片機上不能運行):
abstract class Control {abstract void getCommand(); //是概括了在不同平臺上完成智能家居項目的模板abstract void socketCommand(); //抽象化這些方法,在子類(類比于具體平臺)abstract void lightControl(); //中再進行具體化abstract void cameraControl();public void work(){ //控制的基本流程getCommand(); //接收指令socketCommand(); //來自socket的指令lightControl(); //燈的控制cameraControl(); //相機的控制} }class C51platform extends Control //當這個地方出現紅色波浪線的時候 { //光標放上去,可以看到解決方法的快捷鍵@Override //把抽象方法重寫,全部具體實現void getCommand() {System.out.println("getcommand in 51");}@Overridevoid socketCommand() {System.out.println("socketcommand in 51");}@Overridevoid lightControl() {System.out.println("lightcontrol in 51");}@Overridevoid cameraControl() {System.out.println("cameracontrol in 51");} }public class Test {public static void main(String[] args) {C51platform c51 = new C51platform(); //實例化出一個對象c51.work(); //執行具體流程} }運行結果:
getcommand in 51 socketcommand in 51 lightcontrol in 51 cameracontrol in 51接口
接口的概念
接口(Interface),在JAVA中是一個抽象類型,是抽象方法的集合(重點強調的是方法、是行為,而不是屬性、特征)。
interface 接口名{//公有靜態常量、抽象方法(抽象方法用的比較多) } class 類名{}接口并不是類,編寫接口的方式和類很相似,但是它們屬于不同的概念。類描述對象的屬性和方法。接口則包含類要實現的方法。
接口與類的區別:————————
(1) 接口不能用于實例化對象
(2) 接口沒有構造方法
而類是默認都有構造方法的(系統默認的參數為空的構造方法)
(3)接口中所有的方法必須是抽象方法
可以不指定修飾符,就默認為隱式抽象
(4)接口不能包含成員變量,除了 static 和 final 變量
接口中也一般不適用成員變量,以方法為主。
(5)接口不是被類繼承了,而是要被類實現。而接口可以繼承接口。
說法上的東西罷了,不用太糾結,具體看編程
接口的特點
接口中每一個方法也是隱式抽象的,接口中的方法會被隱式的指定為 public abstract(只能是 public abstract,其他修飾符都會報錯)。
就像下圖,只要你不寫修飾符,那就默認為隱式抽象為public abstract,可以編譯通過。但凡你使用別的修飾符,馬上報錯。
接口的使用
一個類通過繼承接口的方式,從而來繼承接口的抽象方法。
接口無法被實例化,但是可以被實現。一個實現接口的類,必須實現接口內所描述的所有方法(包括接口繼承過來的方法),否則就必須聲明為抽象類。
繼承是有親屬關系的,is的關系;而接口是雙方都有的行為,比如人和狗都要吃東西。
下面的例子是以一些人和狗子都具有的行為作為接口,用Man類和Dog類具體實現:
interface Behavior //接口,更注重方法 {void eat(); //在接口中,不寫修飾符,默認為隱式抽象abstract void drink(); //當然寫也無問題 }class Man implements Behavior //一個類實現了這個接口 { //從而來繼承接口的抽象方法@Overridepublic void eat() {System.out.println("人吃米");}@Overridepublic void drink() {System.out.println("人喝飲料");} }class Dog implements Behavior //一個類實現了這個接口 { //從而繼承接口的抽象方法@Overridepublic void eat() {System.out.println("狗喜歡吃骨頭");}@Overridepublic void drink() {System.out.println("狗喝水");} }public class Test {public static void main(String[] args) {new Man().eat(); //new就是實例化一個對象,所以new Man()已經是一個對象了new Man().drink();new Dog().eat();new Dog().drink();} }接口實現與抽象類繼承的區別
1)抽象類和具體實現之間是一個繼承關系,也就是如果采用抽象類的方式,則父類和子類在概念上應該是相同的 ,是is -a的關系。
比如父類為老師,子類為語文老師,那么可以說語文老師是(is)一個(a)老師。
(2)接口和實現類之間在概念上不要求相同,接口不去關注類之間的關系,它可以使沒有層次關系的類具有相同的行為
抽象類是對一組具有相同屬性和行為的邏輯上有關系的事物的一種抽象。
而接口則重點對一組具有相同行為的事物的一種抽象。
(3)抽象類中的方法可以有方法體,就是能實現方法的具體功能,但是接口中的方法不行。
(4)抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是 public static final 類型的。(但接口強調行為,少用變量)
(5)接口中不能含有靜態代碼塊以及靜態方法(用 static 修飾的方法),而抽象類是可以有靜態代碼塊和靜態方法。
(6)一個類只能繼承一個抽象類,而一個類卻可以實現多個接口
class People implements Survival,EnjoyLife //people這個類實現了多個接口- 1
其實到后面你可以發現,一個類實現多個接口和接口的多繼承再被類實現很像。
接口的多繼承
在Java中,類的多繼承是不合法,但接口允許多繼承。
在接口的多繼承中extends關鍵字只需要使用一次,在其后跟著繼承接口。 如下:(足球這一接口繼承了其他接口)
public interface Sport extends Basketball, Football,Ping_pong- 1
繼承過來后,類依舊要完成所有接口的抽象方法。
舉個簡單的小例子:
interface Survival //人關于生存的行為 {void eat();void drink(); }interface EnjoyLife //人享受生活的行為 {void seeMovie(); }interface HowPeopleLive extends Survival,EnjoyLife //這個接口繼承了上面兩個接口 {void happy();/*void life(){ 接口中不允許有方法體}*/void life(); //只能在類的實現中賦予方法體 }class People implements HowPeopleLive {//當一個類實現接口時,就要把接口里所有的抽象方法實現,具體化@Overridepublic void eat() {System.out.println("主要吃大米飯");}@Overridepublic void drink() {System.out.println("主要喝白開水");}@Overridepublic void seeMovie() {System.out.println("看電影感悟生活");}@Overridepublic void happy() {System.out.println("你開心就好");}@Overridepublic void life() { //實現接口的方法體eat();drink();seeMovie();happy();} }public class Demo1 {public static void main(String[] args) {People man = new People();man.life();} }運行結果:
主要吃大米飯 主要喝白開水 看電影感悟生活 你開心就好內部類
概念
所謂內部類(Inner Class),就是講一個類定義在另一個類的內部,內部的類就稱為內部類。
public class Outer{class Inner{} }內部類可以很好地實現隱藏,成員內部類屬于外部類的實例成員,成員內部類可以有權限修飾符。
可以使用protected private修飾符內部類可以直接訪問外部類的所有成員,包括私有的成員。
外部類不能直接訪問內部類的成員,必須首先建立內部類的對象才能訪問。
成員內部類(使用較多)及應用
創建成員內部類的實例
外部類名.內部類名 實例 = 外部類實例名.new 內部類構造方法(參數)- 1
下面以訪問內部類的方法為例子:
class Outer {int data;void printData(){System.out.println("外部類打印");}class Inner{int data;void innerPrint(){System.out.println("內部類打印");}}}public class Test {public static void main(String[] args) {Outer ou = new Outer(); //要使用內部類的方法,必須先實例化一個外部類的對象Outer.Inner in = ou.new Inner();//再通過這個外部類的對象實例化一個內部類的對象in.innerPrint(); //在進行訪問方法即可} }在成員內部類中訪問外部類的成員方法和屬性
外部類名.this.成員方法 //或者 外部類名.this.成員屬性例如:
class Outer {int data;void printData(){System.out.println("外部類打印");}class Inner{int data;void innerPrint(){System.out.println("內部類打印");Outer.this.printData(); //內部類對外部類方法的訪問System.out.println("內部類訪問外部類的屬性:data="+Outer.this.data);//對屬性的訪問}} }外部類不能直接訪問內部類的成員,必須先建立內部類的對象才能訪問
(意義不大,用的較多的還是內部類訪問外部類)
class Outer {int data;void printData(){System.out.println("外部類打印");}//外部類不能直接訪問內部類的成員,必須先建立內部類的對象才能訪問void visitInner(){Inner in = new Inner();//先建立內部類的對象in.innerPrint(); //通過內部類的對象進行訪問}class Inner{int data;void innerPrint(){System.out.println("內部類打印");}} }public class Test {public static void main(String[] args) {Outer ou = new Outer(); //要使用內部類的方法,必須先實例化一個外部類的對象Outer.Inner in = ou.new Inner();//再通過這個外部類的對象實例化一個內部類的對象ou.visitInner(); //外部類訪問內部類打印} }成員內部類有以下限制
(1)成員內部類不能和外部類重名
(2)不能在成員內部類中定義static屬性、方法、類。(static final形式的常量定義除外)
因為一個成員內部類實例必然與一個外部類實例關聯,static成員完全可以移到其外部類中去。
匿名內部類
概念
匿名內部類是沒有名稱的內部類,沒辦法引用它們。必須在創建時,作為new語句的一部分來聲明并創建它們的實例。
這種形式的new語句聲明一個新的匿名類,它對一個給定的類進行擴展,或者實現一個給定的接口,并同時創建該匿名類的一個新實例。
匿名內部類的創建與訪問
匿名內部類必須繼承一個類(抽象的,非抽象的都可以),或者實現一個接口,所有父類(或者父接口)是抽象類,則匿名內部類必須實現其所有抽象方法。
語法:
new interface/superclass(){類體}- 1
例如:
(1)創建后立即訪問
abstract class Demo1 //聲明了一個抽象類 {abstract void printInfo();//聲明了一個抽象方法 }public class Test {public static void main(String[] args) {new Demo1(){//既初始化又要實現內部的方法 不是實例化 而是創建了匿名內部類并實例化匿名內部類void printInfo(){ //匿名內部類必須實現繼承的類的所有方法System.out.println("這不是demo1,而是匿名內部類的方法");}}.printInfo();//new的返回值就是一個對象,所以可以直接通過“.”這樣訪問匿名內部類的方法} }運行結果:
這不是demo1,而是匿名內部類的方法- 1
(2)當然,也可以用“多態”進行訪問(目前我也不知道多態是啥)
abstract class Demo1 {abstract void printInfo(); }public class Test {public static void main(String[] args) {Demo1 d = new Demo1(){ //這感覺像是實例化了一個Demo1得到對象d,實際上得出的這個Demo1是抽象類的子類void printInfo(){ //匿名內部類必須實現繼承的類的所有方法System.out.println("這不是demo1,而是匿名內部類的方法");}};d.printInfo();} }運行結果:
這不是demo1,而是匿名內部類的方法- 1
(3)匿名內部類實現一個接口
這種用法可能會在安卓的線程,按鍵響應做這樣的事情。
interface Demo2 //接口 {abstract void interprint(); }public class Test {public static void main(String[] args) {new Demo2(){public void interprint(){ //這里不使用public就報錯了System.out.println("這不是接口的實例,而是匿名內部類的方法");}}.interprint();} }運行結果:
這不是接口的實例,而是匿名內部類的方法- 1
總結
以上是生活随笔為你收集整理的Java面向对象(3) —— 抽象类、接口、内部类、匿名内部类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言---------俄罗斯方块(源代
- 下一篇: java美元兑换,(Java实现) 美元