簡體   English   中英

為什么有時我們必須在Android中稱呼super?

[英]Why do we have to call super in Android sometimes?

有時,當我重寫方法時,在第一次調用時會出現異常,如下所示:

05-31 21:32:04.266: E/AndroidRuntime(28471): android.support.v4.app.SuperNotCalledException: 
Fragment AnalFragment{41795860 #1 id=0x7f070002} did not call through to super.onDestroy()

為什么我們被迫調用super.method() 父類有義務是有道理的,但是更重要的是,我們如何知道方法需要調用super而不是等待其崩潰?

為什么我們被迫調用super.method()?

組成Android SDK的類非常復雜。 例如,活動和片段都必須執行許多操作才能正常運行(例如,管理生命周期,優化內存使用,在屏幕上繪制布局等)。 要求客戶端調用基類(通常在方法的開頭)可確保仍然執行這些操作,同時仍為開發人員提供合理的抽象級別。

我們如何知道 函數 方法需要調用super?

文檔應告訴您是否需要這樣做。 如果不是這樣,我會在Google上搜索一些示例代碼(或查看API演示...或者更好的方法,查看源代碼!)。 弄清楚應該不難。

我知道這不是OP的真正意圖,他的確提出了這個問題,而且我不相信它會有很好的答案,因此,如果有人想知道“我為什么要叫超級呢?!他們將需要它,為什么他們不只是為我做!!!” 這是這些問題的答案。

基本上,如果要覆蓋必須調用的東西,則必須調用super(),這通常是相當復雜的代碼。 現在,他們之所以不只是為您執行此操作,而是在您的函數之前調用它的原因主要是為了您可以控制! :-D

更具體地說,如果調用super(),則無法控制,但是可以控制WHEN! 因此,假設您有一些特定的代碼需要在調用super()之前發生,現在,您只有在運行代碼之后才可以調用super()。 或者...假設您要求super()已經為代碼運行而不會崩潰,現在您可以選擇在運行代碼之前運行super(),從而確保為您進行了所有設置。 哎呀,您甚至可以在技術上重寫超類的核心,並編寫自己的方法來處理super()本身,並使其不必調用super(),但是99.9%的時間人們會不需要理智去做這個! :-P

因此,“為什么我必須調用super()”的簡短答案是...,以便您可以控制何時調用它並在super()運行之前或之后進行操作。 :-)

super關鍵字有兩個主要用途

1.調用超類的構造函數。

2.訪問已被子類成員隱藏的超類成員。

那么,為什么有時需要使用超級關鍵字呢? 答案將是android屬於4GL語言,這意味着它具有許多現成的功能。 當我們覆蓋這些方法進行自定義時,我們使用super關鍵字。

請參閱android中super關鍵字的非常簡單用法(因為我們大多數時候都這樣做)。

@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    .
    .
    .
}

super()必須始終是子類的構造函數中執行的第一條語句。 當子類調用super()時,它正在調用其直接超類的構造函數。 super的第二種形式最適用於子類的成員名稱在超類中用相同名稱隱藏成員的情況。

該要求通常直接在API文檔中指定。 例如,請參見android.widget.ListView.onFinishInflate:

受保護的void onFinishInflate()

...

即使子類重寫onFinishInflate,也應始終確保它們調用super方法,以便我們被調用。

不幸的是,我的個人經驗是Android文檔的質量參差不齊。 因此,我懷疑在某些情況下需要致電,但沒有記錄在案。

重要的是要注意,一旦重寫了一個方法,基本上就忽略了父類中的所有內容,而是在子類中擁有了自己的自定義實現(實際上覆蓋了它)!

在我們的案例中,我們不想放棄父實現。 我們實際上希望繼續使用原始方法,並分別為每個子類添加額外的檢查。

這是我們可以使用“ super”關鍵字的地方!

允許您通過使用“ super”關鍵字,后接點和方法名稱來在子類中重用父方法:

例如:isValidMove(position)是用於棋子的方法並檢查移動有效性並綁定在8x8棋盤中。

super.isValidMove(position);

在此處使用關鍵字super意味着我們要從“ this”類的實現內部在super(或父)類中運行實際方法。

這意味着在每個子類中,在檢查自定義運動之前,您可以檢查super.isValidMove(position)是否返回false。 如果是這樣,則無需再進行任何檢查並立即返回false; 否則,請繼續檢查。

Rook類的新實現將如下所示:

class Rook extends Piece{
   boolean isValidMove(Position newPosition){
      // First call the parent's method to check for the board bounds
  if(!super.isValidMove(position)){
     return false;
  }
  // If we passed the first test then check for the specific rock movement
  if(newPosition.column == this.column && newPosition.row == this.row){
     return true;
  }
  else{
     return false;
      }
   }
}

您還可以使用super()來調用父級的構造函數。 通常在實現子代的構造函數時完成。 通常,您首先要在父級構造函數中運行所有內容,然后在子級構造函數中添加更多代碼:

class Rook extends Piece{
   // default constructor
   public Rook(){
    super(); // this will call the parent's constructor
    this.name = "rook";
   }
}

注意:如果子級的構造函數未使用super顯式調用父級的構造函數,則Java編譯器會自動將調用插入到父類的默認構造函數。 如果父類沒有默認的構造函數,則會出現編譯時錯誤。

作為一種基本方法,super是一種用於引用主要超類字段/方法的方法,該類從中完成類擴展(使用初始類定義中的擴展)或從其創建實例。

當我們需要更改超類的方法/字段的最基本定義以解決我們的目的時。

例如

java.lang.Object(有很多方法和字段)> android.view.View> android.view.ViewGroup> android.widget.LinearLayout

但是,如果您需要更改/使用它是對象類的方法,則需要使用Super方法在LinearLayout類內的對象類中引用首次創建的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM