7

I have an abstract parent class with some dependency and a default implementation. The constructors might look like:

  public abstract class ParentClass {
    protected SomeDependency someDependency;

    public ParentClass(SomeDependency someDependency) {
        this.someDependency = someDependency;
    }


}

The dependency itself is a virtual class with methods that might be overridden, for example:

public virtual class SomeDependency {
    public virtual void doSomething() {
        System.debug('#### SomeDependency');
    }
}

The dependency has an extension:

public class ChildDependency extends SomeDependency {
    public override void doSomething() {
        System.debug('#### ChildDependency ');
    }
}

And the child of the original abstract parent looks like this:

public class ChildClass extends ParentClass  {
    public ChildClass() {
        super(new ChildDependency());
    }

    public void doSomething() {
        super.someDependency.doSomething();
    }
}

In this context, I intended that "super" means that "someDependency" lives on the Parent instead of the current object.

However, when I execute this code, I get:

SomeDependency

Which tells me the code is actually interpreting this to mean the parent of ChildDependency.

If I change super.someDependency.doSomething(); to this.someDependency.doSomething();

the code works as I originally expected it to, BUT now the code is "lying" to me because someDependency is actually an instance which lives on the parent and I'd like to make that obvious in my code.

Is there a way I can make my code express this properly?

  • 1
    is SomeDependency someDependency; protected?# – Pranay Jaiswal Jul 19 '19 at 16:32
  • This sounds so weird, ideally the method should be called for the instance that was present. If childDependency instance was passed child method should have been called – Pranay Jaiswal Jul 19 '19 at 16:42
  • have you tried raising a case with SF? – Pranay Jaiswal Jul 19 '19 at 18:55
  • 1
    Interesting, in the docs for super it says "You can only use super in methods that are designated with the override keyword.". That doesn't seem to be the case here. – Daniel Ballinger Jul 23 '19 at 22:12
10

Sounds a bug to me, the instance is still of ChildDependency I confirmed it using debug logs.

public class ChildClass extends ParentClass  {
    public ChildClass() {
        super(new ChildDependency());
    }

    public void doSomething() {
        System.debug( this.someDependency);
        System.debug( super.someDependency);
        this.someDependency.doSomething();
        super.someDependency.doSomething();
    }
}

Execute Anon : new ChildClass().doSomething();

DEUBG:

17:53:16.60 (131753925)|USER_DEBUG|[7]|DEBUG|ChildDependency:[]
17:53:16.60 (131775245)|USER_DEBUG|[8]|DEBUG|ChildDependency:[]
17:53:16.60 (131813593)|USER_DEBUG|[4]|DEBUG|#### ChildDependency
17:53:16.60 (131834856)|USER_DEBUG|[4]|DEBUG|#### SomeDependency

Edit 1: I replicated the same behavior in Java in case anyone wanna do it and its behaving as expected. Java Code demo : https://repl.it/repls/SmugFlawlessUnderstanding

I have a feeling Salesforce Apex Engine uses Java Reflection Like engine to call Apex Methods instead of running Compiled Apex Natively on their servers.

Edit 2: A friend of mine(Thanks Anshul) managed to get it to work by using some unique Syntax.

public class ChildClass extends ParentClass  {

    public ChildClass() {
        super(new ChildDependency());
    }

    public void doSomething() {
        System.debug( this.someDependency);
        System.debug( super.someDependency);
        this.someDependency.doSomething();
        (super.someDependency).doSomething();
    }
}

Yes , (super.someDependency).doSomething(); makes code do what it's supposed to do. Now I wonder if Salesforce uses String parsing to determine keywords and then run Apex code.

Edit 3 : I have managed to convince SF that its a bug and provide a known issue link for it.

https://success.salesforce.com/issues_view?title=super-keyword-in-apex-applies-to-entire-statement-rather-than-proceeding-variable&Id=a1p3A0000003dyw

| improve this answer | |
  • I would have expected the normal order of operations to "calculate" super.someDependency first even with the parenthesis. ... Cheers to you and Anshul for figuring out that this will work. :-) – Brian Kessler Jul 20 '19 at 8:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.