I have a use case where I will have an Apex Class wrapping an sObject, and I need to be able to swap out certain internal functionality based on certain conditions. My plan is to use an few inner classes that implement a common interface, and select them accordingly. To do this, I need to expose certain details of the outer class only to the child classes. This seems like a perfect use case for protected
methods, per the docs (empahsis mine):
protected
This means that the method or variable is visible to any inner classes in the defining Apex class, and to the classes that extend the defining Apex class. You can only use this access modifier for instance methods and member variables. Note that it is strictly more permissive than the default (private) setting, just like Java.
However, trying to do this gives the error "New protected methods cannot be defined in non-virtual classes.
" Seems pretty clear, except that the error contradicts one of the documented use cases; also, I can add protected properties to the outer class without an error.
Here's a simplified class which omits the multiple child classes but which demonstrates the issue:
public class OuterClass {
//this compiles ok if I remove "protected" from getChildren below
protected CustomObject__c obj {get; set;}
public OuterClass(CustomObject__c o) {
this.obj = o;
}
// this method should only be called by Inner Class BusinessLogic
// this is where the compilation error occurs
protected list<ChildObject__c> getChildren() {
return obj.ChildObjects__r;
}
public decimal Calculate() {
BusinessLogic bl = new BusinessLogic(this);
return bl.calculate();
}
private class BusinessLogic {
OuterClass out;
public BusinessLogic(OuterClass oc) {
this.out = oc;
}
public decimal Calculate() {
decimal result = 0;
for (ChildObject__r child : out.getChildren()) {
result += child.Value__c;
}
return result;
}
}
}
I've seen this question about the same error but that only addresses protected virtual
methods. I've also seen this question indicating that inner classes can access private members of the outer class, but that doesn't seem to express my intent. I could make OuterClass virtual, except that it isn't actually virtual. I'll probably just change to private
and be done with it, but I'm wondering if I'm overlooking something? Seems inconsistent that I can make a property protected
(including custom getter/setter if needed) but not a method. Does this seem like an Apex bug or a Documentation bug? Would like a second opinion before I submit an issue.