Java 中extends與implements使用方法

轉自:http://blog.csdn.net/chen_chun_guang/article/details/6323201

初學Java語言, 代碼中的extends和implements讓我感到很迷惑,現在終於弄明白它們之間的區別和用法了。

[c-sharp] view plaincopy
  1. //定義一個Runner接口   
  2. public inerface Runner   
  3. {  
  4.    int ID = 1;  
  5.    void run ();  
  6. }   

 

[java] view plaincopy
  1. //定義一個interface Animal,它繼承於父類Runner  
  2. interface Animal extends Runner  
  3. {  
  4.    void breathe ();  
  5. }  

[c-sharp] view plaincopy
  1. //定義Fish類,它實現了Animal接口的方法run()和breather()  
  2. class Fish implements Animal  
  3. {  
  4.    public void run ()    //實現了Animal方法run()  
  5.  {  
  6.     System.out.println("fish is swimming");  
  7.  }  
  8. public void breather()  
  9.  {  
  10.     System.out.println("fish is bubbing");     
  11.  }  
  12. }  
  13. //定義了一個抽象類LandAnimal,它實現了接口Animal的方法。  
  14. abstract LandAnimal implements Animal  
  15. {  
  16.     
  17.    public void breather ()  
  18.  {  
  19.     System.out.println("LandAnimal is breathing");  
  20.  }  
  21. }  
  22. //定義了一個類Student,它繼承了類Person,並實現了Runner接口的方法run()。  
  23. class Student extends Person implements Runner  
  24. {  
  25.     ......  
  26.     public void run ()  
  27.      {  
  28.           System.out.println("the student is running");  
  29.      }  
  30.     ......  
  31. }  
  32.    
  33. //定義了一個接口Flyer  
  34. interface Flyer  
  35. {  
  36.    void fly ();  
  37. }  
  38.    
  39. //定義了一個類Bird,它實現了Runner和Flyer這兩個接口定義的方法。  
  40. class Bird implements Runner , Flyer  
  41. {  
  42.    public void run ()   //Runner接口定義的方法。  
  43.     {  
  44.         System.out.println("the bird is running");  
  45.     }  
  46.    public void fly ()   //Flyer接口定義的方法。  
  47.     {  
  48.         System.out.println("the bird is flying");  
  49.     }  
  50. }  
  51.    
  52. //TestFish類  
  53. class TestFish  
  54. {  
  55.    public static void main (String args[])  
  56.     {  
  57.        Fish f = new Fish();  
  58.        int j = 0;  
  59.        j = Runner.ID;  
  60.        j = f.ID;  
  61.     }  
  62. }  

 

接口實現的注意點:

a)實現一個接口就是要實現該接口的所有的方法(抽象類除外)。
b)接口中的方法都是抽象的。
c)多個無關的類可以實現同一個接口,一個類可以實現多個無關的接口。


extends與implements的區別:

extends 是繼承父類,只要那個類不是聲明爲final或者那個類定義爲abstract的就能繼承,JAVA中不支持多重繼承,但是可以用接口來實現,這樣就用到了implements,繼承只能繼承一個類,但implements可以實現多個接口,用逗號分開就行了。

比如: 

class A extends B implements C,D,E {}    (class 子類名 extends 父類名 implenments 接口名)

 

父類與子類繼承關係上的不同:

A a = new B(); 結果a是一個A類的實例,只能訪問A中的方法,那麼又和A a = new A();有什麼區別呢?

***********************************************************************************************

class B extends A
繼承過後通常會定義一些父類沒有的成員或者方法。
A a = new B();
這樣是可以的,上傳。
a是一個父類對象的實例,因而不能訪問子類定義的新成員或方法。

***********************************************************************************************

假如這樣定義:
class A

{
   int i;
   void f(){}
}
class B extends A

{
    int j;
    void f(){}       //重寫
    void g(){}
}
然後:
B b = new B();
b就是子類對象的實例,不僅能夠訪問自己的屬性和方法,也能夠訪問父類的屬性和方法。諸如b.i,b.j,b.f(),b.g()都是合法的。此時b.f()是訪問的B中的f()


A a = new B();
a雖然是用的B的構造函數,但經過upcast,成爲父類對象的實例,不能訪問子類的屬性和方法。a.i,a.f()是合法的,而a.j,a.g()非法。此時訪問a.f()是訪問B中的f()

***********************************************************************************************

A a = new B(); 這條語句,實際上有三個過程:
(1) A a;
將a聲明爲父類對象,只是一個引用,未分配空間
(2) B temp = new B();
通過B類的構造函數建立了一個B類對象的實例,也就是初始化
(3) a = (A)temp;
將子類對象temp轉換未父類對象並賦給a,這就是上傳(upcast),是安全的。
經過以上3個過程,a就徹底成爲了一個A類的實例。
子類往往比父類有更多的屬性和方法,上傳只是捨棄,是安全的;而下傳(downcast)有時會增加,通常是不安全的。

***********************************************************************************************

a.f()對應的應該是B類的方法f()
調用構造函數建立實例過後,對應方法的入口已經確定了。
如此以來,a雖被上傳爲A類,但其中重寫的方法f()仍然是B的方法f()。也就是說,每個對象知道自己應該調用哪個方法。
A a1 = new B();
A a2 = new C();
a1,a2兩個雖然都是A類對象,但各自的f()不同。這正是多態性的體現。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章