views:

31

answers:

1

I have a class that has a method. That class has a child class that overrides that method. The child's method has to call the parent's method. In all OO that I've seen or written calls to the parent's version of the same method were on the first line of the method. On a project that I am working on circumstances call for placing that method call at the end of a method. Should I be worried? Is that a code smell? Is this code inherently bad?

class Parent {
    function work() {
        // stuff
    }
}

class Child {
    function work() {
        // do thing 1
        // do thing 2
        parent::work(); // is this a bad practice?
        // should I call the parent's work() method before 
        // I do anything in this method?
    }
}
A: 

As you said yourself, circumstances called for that ordering. There are no stylistic "rules" as to the order in which a parent's implementation has to be called, it fully depends on implementation-specific factors. You may even find instances in which the parent implementation has to be called conditionally.

The only special cases when it makes sense for parent implementations to always be called first (or last) are constructors (and destructors). In these cases, ordering is important so that, by the time thing1 and thing2 (in your example) execute, your object's ancestry has already been fully constructed (or not yet destructed.) In all other cases (regular methods) it is up to you to pick the ordering which best suits your business logic needs.

This having been said, coming back to your example, I'd worry more about whether you want work() to be virtual or not in those languages where this is an option. :)

class BasicLogger {
    BasicLogger() {
        // open log file
    }
    virtual function log(string s) {
        // write to log file
    }
}

class TimestampedLogger extends BasicLogger {
    TimestampedLogger () {
        // consructor calling order enforced in most OOP languages
        BasicLogger();           // must be called first to open log file,
        log("logging started");  //  or else writing to the log will fail
    }
    virtual function log(string s) {
        s = timestamp() + ": " + s;
        super.log(s); // nothing wrong with this
    }
}

class ConditionalLogger extends TimestampedLogger {
    ConditionalLogger () {
        TimestampedLogger();
        log("log level is " + logLevel());
    }
    virtual function log(string s) {
        if (logLevel() > INFO) {
            super.log(s); // nothing wrong with this either
        }
    }
}
vladr