什么时候不要在覆盖时调用super()方法?

问题

当我创建自己的Android自定义类时,Iextendits是本机类。然后,当我想覆盖基本方法时,我总是调用super()方法,就像我总是在onCreate,onStop等。

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

但是,在中,很多书我都可以看到,比我更有经验的开发人员经常省略调用super而且我真的怀疑他们这样做是因为缺乏知识。例如,看看这个basicSAXparser类,其中superstartElement,characters和2889581799中省略:

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创建任何覆盖方法,super将始终作为自动化过程的一部分创建。

这只是一个简单的例子。书籍是**,类似代码**。

他们怎么知道什么时候你必须打电话super以及什么时候可以省略它?

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

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


#1 热门回答(133 赞)

通过调用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()将按此特定顺序执行ABsave()逻辑。如果你没有打电话super.save()insideB.save(),A.save()将无法召唤。如果你之后打电话super.save()save(b),A.save()将会有效地执行B.save()

如果你想要覆盖super的行为(也就是说,完全忽略它的实现并自己提供),你不应该调用super

在你提供的SAXParser示例中,这些方法的implementations,DefaultHandler只是空的,因此子类可以覆盖它们并为这些方法提供行为。在这种方法的javadoc中也指出了这一点。

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

关于super()在IDE生成的代码中的默认调用,as@barsju在他的注释中指出,在每个构造函数中有一个隐式调用tosuper()(即使你没有在你的代码中编写它),这意味着,在该上下文中,调用super的默认构造函数。 IDE只是为你写下来,但如果删除它也会被调用。还要注意,在实现构造函数时,super()或其带参数的任何变体(即,4037538956)只能在方法的最开头调用。


#2 热门回答(15 赞)

他们怎么知道什么时候你必须打电话给超级,什么时候你可以省略它?

通常情况下,如果一个特殊的API方法具有关键意义的底层框架范围内的生命周期,它总是会被明确说明和API文档中突出显示,如theActivity.onCreate()API文档。此外,如果API遵循强大的设计,它应该抛出一些异常,以便在项目编译时提醒消费者开发人员,并确保它不会在运行时生成错误。

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

如果条件允许(我喜欢开源软件),消费者开发人员总是可以查看API源代码,看看该方法是如何实际编写的。例如,请查看Activity.onCreate()sourceandDefaultHandler.startElement()source。


#3 热门回答(7 赞)

你应该在头脑中做的测试是:

"我是否希望为我完成此方法的所有功能,然后再做一些事情?"如果是,那么你想调用314141689,然后完成你的方法。这对于"重要"方法也是如此,例如onDraw(),它在后台处理很多事情。

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