[SalesForce] Overriding a global method with a public method

When you define an abstract method of a class as public or global, an attempt to change the access modifier to protected or private when overriding the method produces a compile time error:

Cannot reduce the visibility of method: …

Similarly for interface methods,

Overriding implementations of global or public interface methods must be global or public: …

But why is it that Apex allows you to use the public and global access modifiers interchangeably?

Are there useful managed package design patterns that involve making a global method public for some subtypes of your class/interface?


Here is an example that the compiler allows:

An abstract class SuperClass

global abstract class SuperClass
{
    global abstract void superClassMethod();    
}

An interface MyInterface

global interface MyInterface{

    void interfaceMethod();

}

A subclass that implements the interface SubClass1

global class SubClass1
       extends SuperClass
       implements MyInterface
       {

    // Note the access modifiers    
    global override void superClassMethod(){ }

    global void interfaceMethod(){ }

}

Another subclass that implements the interface SubClass2

global class SubClass2
       extends SuperClass
       implements MyInterface
       {

    // Note the access modifiers
    public override void superClassMethod(){  }

    public void interfaceMethod(){  }

}

Best Answer

global and public are essentially synonyms. The only difference is that global methods and interfaces can be accessed outside of the package's code. I can see this as useful in a few situations. Perhaps you want to define an interface that can be used in a global context (e.g. to provide plugin access points for your subscribers), but you also have classes that you want to protect from being called externally that happen to implement these interfaces.

This can be advantageous for two primary reasons: (1) global methods can't be "deleted", so declaring something global might limit future development, and (2) public methods can't be called outside the package. I'm sure someone somewhere out there is using this pattern, but I'd also be willing to bet that this is probably an incredibly rare use case. Without someone at Salesforce explicitly mentioning why the two are interchangeable, the best we can do is guess as to the original intent.

I suspect that this is intentional, though, because it makes sense that you'd want to be able to have a global default implementation yet be able to hide specific sub-implementations that clients shouldn't call directly. Either way, I would carefully consider the possible effects of mixing the two. Generally speaking, if it's not client-callable code, don't make it global. Always provide the minimum access level necessary that works for the intended design.

Related Topic