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.