当重写时不要调用super()方法?

当我创build自己的Android自定义类时,我extend它的本地类。 然后当我想重写基方法时,我总是调用super()方法,就像我总是在onCreateonStop等一样

我认为就是这样,从一开始Android团队build议我们总是在每个方法覆盖面上调用super

但是,在许多书中,我可以看到,比我更有经验的开发者经常忽略super调用,我真的怀疑他们是否缺乏知识。 例如,查看startElementcharactersendElement省略super基本SAXparsing器类:

 public class SAXParser extends DefaultHandler{ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(qName.equalsIgnoreCase("XXY")) { //do something } } public void characters(char[] ch, int start, int length) throws SAXException { //do something } public void endElement(String uri, String localName, String qName) throws SAXException { if(qName.equalsIgnoreCase("XXY")) { //do something }else () { //do something } } } 

如果您尝试通过Eclipse或任何其他IDE创build任何重写方法, super将始终作为自动化过程的一部分创build。

这只是一个简单的例子。 书籍充满了类似的代码

他们如何知道什么时候你必须打电话给super电话,什么时候可以忽略电话?

PS。 不要绑定到这个具体的例子。 这只是从许多例子中随机挑选的一个例子。

(这可能听起来像一个初学者的问题,但我真的很困惑。)

通过调用super方法,您不会覆盖该方法的行为,而是在扩展它。

super的调用将执行您正在扩展的类为该方法定义的任何逻辑。 考虑到在您的方法覆盖中调用super实现的时候,这可能很重要。 例如:

 public class A { public void save() { // Perform save logic } } public class B extends A { private Object b; @Override public void save() { super.save(); // Performs the save logic for A save(b); // Perform additional save logic } } 

B.save()调用将按照此特定顺序为AB执行save()逻辑。 如果你没有在B.save()调用super.save()则不会调用super.save() 。 如果在save(b) super.save()之后调用了super.save()A.save()将在后来的B.save()被有效执行。

如果你想覆盖 super的行为(即完全忽略它的实现并自己提供),你不应该叫super

在您提供的SAXParser示例中,这些方法的DefaultHandler的实现只是空的,以便子类可以覆盖它们并为这些方法提供行为。 在这个方法的javadoc中也指出了这一点。

 public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { // no op } 

关于由IDE生成的代码中的super()默认调用,就像@barsju在他的注释中指出的那样,在每个构造函数中都有一个隐式调用super() (即使你不把它写在你的代码中),也就是说,在这种情况下,调用super的默认构造函数。 IDE只是为你写下来的,但如果你删除它,它也会被调用。 另外请注意,在实现构造函数时,只能在方法的最开始调用super()或任何带参数的变体(即super(x,y,z) )。

他们如何知道什么时候你必须打电话给超级电话,什么时候可以忽略电话?

通常,如果一个特殊的API方法对底层框架上下文的生命周期有着至关重要的意义,那么它总是会在API文档中明确地陈述和强调,比如Activity.onCreate() API文档 。 而且,如果API遵循一个健壮的devise,则应该在项目编译时抛出一些exception来提醒消费者开发人员,并确保在运行时不会产生错误。

如果在API文档中没有明确说明这一点,那么消费者开发人员认为在覆盖API方法时不强制要求调用是非常安全的。 由消费者开发者决定是使用默认行为(调用super方法)还是完全覆盖它。

如果条件允许的话(我喜欢开源软件),消费者开发者可以随时检查API源代码,看看这个方法是如何写在底层的。 例如,查看Activity.onCreate()源和DefaultHandler.startElement()源 。

你应该做的testing是:

“我是否希望为我完成这个方法的所有function,然后再做一些事情? 如果是,那么你想调用super() ,然后完成你的方法。 这对于“重要的”方法来说是正确的,例如onDraw() ,它在后台处理很多东西。

如果你只想要一些function(就像你将覆盖的大多数方法一样),那么你可能不想调用super()

那么哈维给了一个更好的答案..但你可能会知道super()做什么时调用重写的方法…它广告你做了什么默认行为..

例如:

 onDraw() 

方法在视图类中被重写时,你说的super.onDraw()之前,它出现一旦视图完全绘制..所以这里调用super是必要的,因为android有一些关键的重要事情要做(如onCreate())

但在同一时间

 onLongClick() 

当你重写这个你不想调用超级,因为它带来了EditText的选项列表或任何其他类似的视图..这就是基本的差异..你可以select离开它一些..但是其他方法像onCreate() , onStop()你应该让操作系统处理它..

我没有清楚地说明你的问题,但如果你问为什么不调用super方法:

有一个调用super方法的原因:如果在父类中没有零参数构造函数,那么就不可能为它创build一个子类,所以要么在父类中保留一个没有参数的构造函数,要么需要使用argument(how much argument constructor you have used in super class)在子类构造函数的顶部定义super()调用语句。

我希望这有帮助。 如果没有,让我知道。

我实现了一个约束数组列表

 public class ConstraintArrayList<T> extends ArrayList<T> { ConstraintArrayList(Constraint<T> cons) {this.cons = cons;} @Override public boolean add(T element) { if (cons.accept(element)) return super.add(element); return false; } } 

如果你看代码,它只是在实际让超类执行实际的元素添加到列表之前进行一些预检。 这说明了方法覆盖的两个重要原因之一:

  1. 扩展性,你想扩展什么超类可以做
  2. 你想通过多态性来添加特定行为的特殊性,例如在鸟类移动(飞行)和青蛙移动(跳跃)方式的移动语义的常见动物王国示例中对于每个子类都是特定的。