本文主要講解了java中抽象類與接口的概念、使用及它們之間的區別。這部分知識是屬于java語言中核心的知識,是我們理解面向對象思想及代碼設計必要掌握的內容。
2 抽象類
2.1 概念及案例
假設有一個Employee和Student類,考慮一下對這兩個類的擴展。比如每個員工或者學生都有姓名,因此可以將name放在較高層次的超類Person中。另外可以在Person中再添加一個方法getDescription,它可以返回對一個人的描述。因為不知道這個人是學生還是員工,所以該方法是抽象(abstract)的,也就是沒有方法體的。
如下代碼:
public abstract class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
public abstract void getDescription();
}
抽象類要使用關鍵字:abstract
抽象類中除了可以包含抽象方法外,也可以包含具體數據和具體方法。抽象方法充當一個占位的角色。
擴展抽象類可以有兩種選擇:
Ø 一種是在子類中定義部分抽象方法或不定義抽象方法,這樣就必須將子類也標記為抽象類;
Ø 另一種是定義全部的抽象方法,這樣子類就不是抽象的了。
類即使不含抽象方法,也可以將類聲明為抽象的,不過這樣沒有什么意義。
抽象類不能被實例化。也就是說,將一個類聲明為abstract,就不能創建這個類的對象了,但是可以創建一個具體子類的對象。需要注意的是,可以定義一個抽象類的對象變量,但是它只能引用非抽象子類的對象:Person p = new Student();//這里p是一個抽象類Person的變量,但他引用非抽象子類Student的實例。
public class Student extends Person{
public Student(String name) {
super(name);
}
@Override
public void getDescription() {
System.out.println("我是一個學生!");
}
}
3 接口
3.1 概述
接口(interface)技術,主要是用來描述類具有什么功能,而并不給出每個功能的具體實現。一個類可以實現(implement)一個或多個接口。
在java語言中,接口不是類,而是對一組需求的描述,實現接口的類要遵從接口描述的統一格式進行定義。
3.2 案例
Arrays類中的sort方法可以對對象數組進行排序,但前提是:對象所屬的類必須實現了Comparable接口。
下面是Comparable接口的代碼:
public interface Comparable
public int compareTo(T o);
}
任何實現Comparable接口的類都需要包含compareTo方法,并且這個方法的參數是一個泛型類型。
返回一個整數值。
說明:在調用x.compareTo(y)的時候,當x小于y時,返回一個負數;當x等于y時,返回0;當x大于y時,返回一個正數。
接口中的所有方法自動地屬于public。因此,在接口中聲明方法時,也可以不必提供關鍵字public.
Comparable接口只有一個方法,有些接口是可能包含多個方法的。
在接口中還可以定義常量。
接口絕不能含有實例域,也不能在接口中實現方法。(提供實例域和方法實現的任務應該由實現接口的類來完成)
假設希望使用Arrays類的sort方法對Employee對象數組進行排序,Employee類就必須實現Comparable接口。
實現一個接口,通常需要下面兩個步驟:
1. 將類聲明為實現給定的接口(使用關鍵字implements)
2. 對接口中的所有方法進行定義
下面是具體代碼:
package com.ck.entity;
public class Employee implements Comparable<Employee>
private String name;
private double salary;
public Employee(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public Employee() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + "]";
}
@Override
public int compareTo(Employee o) {
return Double.compare(salary, o.getSalary());
}
}
@Test
public void test1(){
Employee[] emps = new Employee[3];
emps[0] = new Employee("王五",2000);
emps[1] = new Employee("張三", 5000);
emps[2] = new Employee("李四", 4000);
Arrays.sort(emps);
for (Employee employee : emps) {
System.out.println(employee.toString());
}
}
3.3 接口的特性
1. 接口不是類,尤其不能使用new關鍵字實例化一個接口;
2. 雖然不能實例化接口,但可以聲明接口的變量:Comparable x = new Employee();
3. 如同使用instanceof檢查一個對象是否屬于某個特定類一樣,也可以使用instanceof檢查一個對象是否實現了某個特定的接口:if(anObject instanceof Comparable){…}
4. 與可以建立類的繼承關系一樣,接口也可以擴展:public interface A{} public interface B extends A{}
5. 雖然接口中不能包含實例域或者靜態方法,但卻可以包含常量:public interface A{ double x=50; },與接口中的方法都自動的被設置為public一樣,接口中的域將被自動設為public static final
6. 每個類只能擁有一個超類,但卻可以實現多個接口。public class A implement B,C{}
4 接口與抽象類的區別
4.1 語法方面的區別
1. 抽象類可以提供成員方法的實現細節,而接口中只能存在public abstract方法;
2. 抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的;
3. 接口中不能含有靜態代碼塊及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
4. 一個類只能繼承一個抽象類,但卻可以實現多個接口
4.2 設計方面的區別
抽象類是對一種事物的抽象,即對類的抽象;而接口是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為;接口是對類局部(行為)進行抽象。比如:飛機和鳥不是同類的事物,但是它們都有一個共性---會飛。那么在設計的時候,可以將飛機設計為一個類Plane,將鳥設計為一個類Bird,但是不能將飛行這個特性也設計為一個類,因為它只是一個行為,并不是對一類事物的抽象描述。此時,可以將飛行設計為一個接口Fly,包含方法fly(),然后Plane和Bird分別根據自己的需要實現Fly這個接口。然后至于有不同種類的飛機,比如戰斗機、民用飛機等直接繼承Plane即可,對于鳥類也是類似的,不同種類的鳥直接繼承Bird類即可。(從這個例子中能看出,繼承是一個“是不是”的關系,而接口實現則是“有沒有、具備不具備”的關系)