5

I've encountered with a bit strange issue which breaks my understanding of basic OOP principles.

In short, there are two classes: parent (virutal) and child (extends parent). Both of them have private method with the same name and signature. This private method is called right from the constructors. When instance of child class is created, private method from child class is called twice, and no call to the method from the parent class.

Bellow is the snippet of code to reproduce this behaviour: two classes and debug log output.

Parent class:

public without sharing virtual class BoomParentClass {

    public BoomParentClass() {

        System.debug('XXX: Hello from BoomParentClass constructor');

        init();

    }


    private void init() {

        System.debug('XXX: Hello from BoomParentClass init method');

    }


}

Child class:

public without sharing virtual class BoomChildClass extends BoomParentClass {

    public BoomChildClass() {

        System.debug('XXX: Hello from BoomChildClass constructor');

        init();

    }


    private void init() {

        System.debug('XXX: Hello from BoomChildClass init method');

    }


}

The command I'm executing:

new BoomChildClass();

Debug log outputs:

14:00:30:094 USER_DEBUG [6]|DEBUG|XXX: Hello from BoomParentClass constructor
14:00:30:094 USER_DEBUG [15]|DEBUG|XXX: Hello from BoomChildClass init method
14:00:30:094 USER_DEBUG [6]|DEBUG|XXX: Hello from BoomChildClass constructor
14:00:30:094 USER_DEBUG [15]|DEBUG|XXX: Hello from BoomChildClass init method

Why is it like that ? I thought private method belongs to the class itself and can't be overriden (that's why they are called 'private'). Any help would be appreciated.

1

1 Answer 1

0

A virtual subclass or method that's declared as virtual can be overridden when the class is extended, but only if using the override keyword (see Extending a Class and Extended Class Example).

I suspect what's happening here is that you're seeing this behavior because you've used private void init() once again when you extended the original class. This is something I'd have expected the compiler to catch and not allow you to do. But then again, perhaps it expects that you know what you're doing when writing the extension?

It's definitely behaving as though it allowed you to override the method being called from your extension's constructor, which may be part of the issue. With many extensions, there's an implicit constructor or the original constructor is used for the extended class, after which additional methods are available.

When I test, your problem disappears if you change your code as follows:

public without sharing virtual class BoomChildClass extends BoomParentClass {

    public BoomChildClass() {

        System.debug('XXX: Hello from BoomChildClass constructor');

        init2();

    }


    private void init2() {

        System.debug('XXX: Hello from BoomChildClass init method');

    }


}

Debug Log:

09:30:17:025|USER_DEBUG|[5]|DEBUG|XXX: Hello from BoomParentClass constructor 09:30:17:025|USER_DEBUG|[14]||DEBUG|XXX: Hello from BoomParentClass init method 09:30:17:025|USER_DEBUG|[5]|DEBUG|XXX: Hello from BoomChildClass constructor 09:30:17:025|USER_DEBUG|[14]|DEBUG|XXX: Hello from BoomChildClass init method

1
  • 1
    Yep, that's workaround I've used to bypass the problem, i.e. just use another name for init method in child class. Don't know, but for me this behaviour looks very dangerous, especially when extending some class from manage package (I have no idea what private methods are used there). So I could easily break the logic just by accidentally choosing 'bad' name for private method in my class. Really weird behaviour for object-oriented language.
    – wesaw
    May 17, 2015 at 15:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .