1. 程式人生 > >java面向對象基礎(四):抽象類和接口

java面向對象基礎(四):抽象類和接口

microsoft php cat blog ini htm end arch pin

抽象類(abstract)

  1. 使用abstract關鍵字來修飾的類是抽象類。使用abstract修飾方法時這個方法稱為抽象方法。
  2. 含有抽象方法的類必須被聲明為抽象類,抽象類必須被繼承,抽象方法必須被重寫。
  3. 抽象類不能被實例化,即不能new該類對象。因為抽象類是比較抽象的類,是殘缺不全的類。
  4. 抽象方法只需定義它的結構,不需寫方法體。因為抽象方法最終都要被子類重寫,即使定義抽象方法也是多余的。
  5. 抽象類中並非一定要包含抽象方法,也並非不能包含普通方法。

以下面多態的示例來說明:

class Animal {
  private String name;
  Animal(String name) {this
.name = name;} public void sing(){System.out.println("animal sing...");} //這是多余的方法 } class Cat extends Animal { private String eyeColor; Cat(String n,String c) {super(n); eyeColor = c;} public void sing() {System.out.println("cat sing...");} } class Dog extends Animal { private
String furColor; Dog(String n,String c) {super(n); furColor = c;} public void sing() {System.out.println("dog sing...");} } class Lady { private String name; private Animal pet; Lady(String name,Animal pet) {this.name = name; this.pet = pet;} public void myPetSing(){pet.sing();} } public class DuoTai { public static void main(String args[]){ Cat c = new Cat("catname","blue"); Dog d = new Dog("dogname","black"); Lady l1 = new Lady("l1",c); Lady l2 = new Lady("l2",d); l1.myPetSing(); l2.myPetSing(); } }

父類Animal中的sing()方法遲早要被子類Cat、Dog重寫,而且在多態實現下,Animal的sing()完全是多余的。因此,可以將Animal的sing()方法的方法體刪掉。

class Animal {
  private String name;
  Animal(String name) {this.name = name;}

  public void sing() {}
}

更徹底一點,將sing()方法加上abstract關鍵字,這個方法變為抽象方法,抽象方法是不完整的方法,它必須被子類重寫。抽象方法所在的類也必須加上abstract關鍵字變成抽象類。成了抽象類後這個類也是不完整的類,所以無法實例化new Animal

abstract class Animal {
  private String name;
  Animal(String name) {this.name = name;}

  public abstract void sing();
}

雖然Animal中的sing()用不上了,但它卻必須要定義出來,因為它要被子類重寫。另外,如果子類不想重寫抽象方法,可以將這個子類也定義為抽象類,並讓子子類去重寫。

接口(interface)

接口定義的是一種具有某種能力的標準,通過接口實現的方式來體現如何具有該這些能力。說白了它就是能實現某些能力的標準。

例如定義一個USB接口的標準,各廠商如何去實現這個標準由各廠商自己去決定,但不管如何,各廠商實現的USB接口必須達到標準所要求具有的能力。

放在編程語言中來說,接口是一種特殊的抽象類,裏面的方法必須全部是抽象方法且都是public的,裏面的變量也必須都是"public static final"屬性的。即使不寫這些修飾關鍵字,默認也是這些屬性,但如果寫了,就絕對不能寫錯。

定義接口的方式是使用interface關鍵字替代class關鍵字。例如以下定義一個Singable接口,要求必須有喉嚨,且能唱歌,能臨時停止唱歌。

interface Singable {
    public static final boolean houlong = true;

    public void sing();
    public void tmpStop();
}

既然接口是一種抽象類,那麽就可以被繼承,且裏面的方法必須要重寫以體現各子類獨有的能力。通常接口都被命名為"XXXable",因為接口一般體現的是具有某種能力。

繼承接口這個特殊類的術語是"實現接口",使用implement關鍵字。某個類可以實現多個接口,也就是"多重繼承"。不僅如此,實現接口的同時還可以實現extends繼承其他類。有以下幾種寫法:

class A implement intf1 {}
class A implement intf1,intf2 {}
class A extends ParentClass implement intf1,intf2 {}

以下是一個示例,定義了Singable和Paintable兩個接口,還定義了兩個實現這兩接口的類Student和Teacher,它們分別有各自的方法study()和teach()。

interface Singable {
    public void sing();
}

interface Paintable {
    public void paint();
}

class Student implements Singable {
    private String name;
    Student(String name) {this.name = name;}

    public void study() {System.out.println("Student studing...");}

    // overwrite methods 
    public void sing() {System.out.println("Student singing...");}
}

class Teacher implements Singable,Paintable {
    private String name;
    Teacher(String name) {this.name = name;}

    public void teach() {System.out.println("Teacher teaching...");}

    // overwrite methods 
    public void sing() {System.out.println("Teacher singing...");}
    public void paint() {System.out.println("Teacher painting...");}
}

public class Interface {
    public static void main(String[] args) {
        Singable s1 = new Student("Malongshuai");
        s1.sing();
        //s1.study();   //return error! because s1 upcasting from Student to Singable
        Student s = (Student)s1;
        s.study();  //return true

        Singable t1 = new Teacher("Gaoxiaofang");
        t1.sing();
        //t1.paint(); //return error! t1 upcasting from Teacher to Singable,not Paintable
        Paintable t = (Paintable)t1;
        t.paint();
    }
}

上面的示例中,Student類實現了Singable接口,所以它重寫了sing(),Teacher類實現了Singable接口和Paintable接口,所以它重寫了sing()和paint()。

需要註意的點在於接口和實現接口的類之間具有多態性。正如上面的Singable t1 = new Teacher("Gaoxiaofang");,此時t1雖然引用的是Teacher對象,但它能識別的數據只有Singable接口的成員sing(),而無法識別Teacher自身的方法teach()和Paintable接口的方法paint(),且因為子類Teacher重寫了Singable中的sing(),所以多態性使得t1.sing()調用的是Teacher重寫後的sing()。要訪問paint(),需要將t1轉型為Paintable類型或者Teacher類型,要訪問teach(),就必須轉型為Teacher類型。

註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!

java面向對象基礎(四):抽象類和接口