1. 程式人生 > 其它 >淺析extends與implements的區別、繼承向上轉型及上轉具體過程

淺析extends與implements的區別、繼承向上轉型及上轉具體過程

一、extends與implements的區別

1、在類的宣告中,通過關鍵字extends來建立一個類的子類。

  一個類通過關鍵字 implements 宣告自己使用一個或者多個介面。

  extends 是繼承某個類,繼承之後可以使用父類的方法,也可以重寫父類的方法。

  implements 是實現多個介面,介面的方法一般為空的,必須重寫才能使用

2、extends是繼承父類,只要那個類不是宣告為final或者那個類定義為abstract的就能繼承

  Java中不支援多重繼承,但是可以用介面來實現,這樣就要用到 implements,繼承只能繼承一個類,但 implements 可以實現多個介面,用逗號分開就行了。比如 :class A extends B implements C,D,E

3、介面實現的注意點:

(1)實現一個介面就是要實現該介面的所有的方法(抽象類除外)

(2)介面中的方法都是抽象的

(3)多個無關的類可以實現同一個介面,一個類可以實現多個無關的介面

4、與Extends的不同

  extends 可以實現父類,也可以呼叫父類初始化 this.parent(),而且會覆蓋父類定義的變數或者函式。這樣的好處是:架構師定義好介面,讓工程師實現就可以了,整個專案開發效率和開發成本大大降低。

  implements 實現父類,子類不可以覆蓋父類的方法或者變數。即使子類定義與父類相同的變數或者函式,也會被父類取代掉。

  這兩種實現的具體使用,是要看專案的實際情況,需要實現,不可以修改implements,只定義介面需要具體實現,或者可以被修改擴充套件性好,用extends。

二、extends的向上轉型

  父類與子類繼承關係上的不同:A a = new B(); 結果a是一個A類的例項,只能訪問A中的方法,那麼又和A a = new A();有什麼區別呢?

  class B extends A,繼承過後通常會在 B 類上定義一些父類 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)有時會增加,通常是不安全的。

4、需要注意的是:

  a.f() 對應的應該是B類的方法 f(),因為呼叫建構函式建立例項過後,對應方法的入口已經確定了

  如此一來,a 雖被上轉為 A類,但其中重寫的方法f()仍然是B的方法f()。也就是說,每個物件知道自己應該呼叫哪個方法。

A a1 = new B();
A a2 = new C();

  a1,a2兩個雖然都是A類物件,但各自的 f() 不同,這正是多型性的體現