为什么我们有时必须在Android中调用super?

时间:2012-06-01 01:36:16

标签: java android inheritance override

有时当我覆盖方法时,我第一次调用它时会出现异常:

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,而不是等待它崩溃?

6 个答案:

答案 0 :(得分:40)

  

为什么我们被迫调用super.method()?

构成Android SDK的类可能非常复杂。例如,活动和片段必须执行许多操作才能正常工作(即管理生命周期,优化存储器使用,将布局绘制到屏幕等)。要求客户端调用基类(通常在方法的开头)确保仍然执行这些操作,同时仍为开发人员提供合理的抽象级别。

  

我们如何知道函数 方法需要调用super?

文档应该告诉您这是否是必需的。如果不是,我会谷歌搜索一些示例代码(或检查API演示......或者更好,请查看源代码!)。弄清楚应该不难。

答案 1 :(得分:14)

我知道这不是OP的真正意图,他确实提出了这个问题,我不相信它有一个非常好的答案所以,如果有人想知道“为什么我要打超级? !如果他们要求它,他们为什么不这样做呢!!!“。以下是这些问题的答案......

基本上,如果你要覆盖必须被调用的东西,那么必须调用super(),这通常是相当复杂的代码。现在,他们不仅为你做这件事并在你的功能之前调用它的原因主要是让你有控制权! :-D

更具体地说,如果你调用super(),则无法控制,但是,你可以控制WHEN! 所以,假设你有一些特定的代码需要在super()被调用之前发生,你现在可以自由地在运行你的代码之后调用super()。或者......假设您需要super()已经为您的代码运行而不会崩溃,您现在可以选择在运行代码之前运行super(),从而确保为您设置所有内容。哎呀,你甚至可以在技术上覆盖超类硬核并编写你自己的方法来处理super()本身,然后使它不需要调用super(),但99.9%的时间是理智的人不需要去做这个! :-P

所以,“为什么我必须调用super()”的简短回答是......这样你就可以控制它何时被调用并在之前或者在运行super()之后执行操作。 : - )

答案 2 :(得分:9)

超级关键字有两个主要用途

1。调用超类的构造函数。

2. :访问由子类成员隐藏的超类成员。

那么,为什么有时需要使用超级关键字呢?答案将是android下4GL语言,这意味着它已经准备好了很多功能。虽然我们覆盖了这些自定义方法,但我们使用了super关键字。

在android中看到super关键字的非常简单的用法(因为我们大部分时间都这样做)。

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

super()必须始终是子类'构造函数内执行的第一个语句。当子类调用super()时,它正在调用其直接超类的构造函数。第二种形式的super最适用于子类的成员名称在超类中使用相同名称隐藏成员的情况。

答案 3 :(得分:3)

该要求通常直接在API文档中指定。例如,请参阅android.widget.ListView.onFinishInflate:

  

protected void onFinishInflate()

     

...

     

即使子类重写onFinishInflate,它们也应该始终确保调用super方法,以便我们调用它。

不幸的是,我个人的经验是Android文档的质量参差不齐。所以,我怀疑有些情况需要调用,但没有记录。

答案 4 :(得分:1)

重要的是要注意,一旦覆盖了一个方法,你基本上会忽略父类中的所有内容,而是在子类中拥有自己的自定义实现(直接覆盖它)!

在我们的案例中,我们不想丢弃父实现。我们实际上希望继续使用原始方法,并分别为每个子类添加额外的检查。

这是我们使用" super"关键字!

您可以使用" super"在子类中重用父方法。关键字,后跟一个点,然后是方法名称:

例如:isValidMove(position)是棋子和方法的方法。检查移动有效性&绑定在8x8棋盘上。

super.isValidMove(位置);

在这里使用关键字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编译器会自动插入对父类的默认构造函数的调用。如果父类没有默认构造函数,则会出现编译时错误。

答案 5 :(得分:0)

作为一个基本的,super是一个方法,用于引用完成类扩展的主要超类字段/方法(在初始类定义中使用extends)或者从中创建其实例。

当我们需要一个最基本的定义来改变超类的方法/字段来解决我们的目的。

例如

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

但是如果你需要更改/使用它,因为它是Object Class的一个方法,那么你需要Super方法来引用第一次创建的方法在对象类中 LinearLayout类。