2

I have a virtual class with non virtual and virtual methods:

public virtual class ComponentVisibility {
    protected Id currentUserId = null;
    protected String currentUserRole = '';
    protected String currentProfileName = '';
    
    protected User user = null;

    protected void setProfileName() {
        currentProfileName = [
            SELECT Name
            FROM profile 
            WHERE id =: userInfo.getProfileId()
        ].Name;
    }
    
    protected virtual void setRecordOwnerId() {}
    .
    .
    .
    .
}

I have a child class:

public class LeadComponentVisibility extends ComponentVisibility {
    private Id leadId;
    private Id leadOwnerId;
    private String leadOwnerRole;
    

    public override void setRecordOwnerId() {
    leadOwnerId = [
            SELECT id, OwnerId
            FROM Lead
            WHERE id =: this.leadId
        ].OwnerId;
    }
}

If I instantiate LeadComponentVisibility lcv = new LeadComponentVisibility(); in another class LeadComponentVisibilityFacade and call lcv.setRecordOwnerId();, works fine. But if call lcv.setProfileName(), I get Method is not visible: void ComponentVisibility.setProfileName(). If I make setProfileName() Public it works. Why? Isn't setProfileName() inherited?

If I do ComponentVisibility leadComponentVisibility = new LeadComponentVisibility(); instead of LeadComponentVisibility lcv = new LeadComponentVisibility(); and call leadComponentVisibility.setRecordOwnerId(); I get the same Method is not visible error. Why?

I did read the doc which says:

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.

So what am I doing wrong.

1 Answer 1

5

Protected behaves like private, except that child classes can access the methods or properties. So, LeadComponentVisibility can call the method, because it is a descendant, but other classes cannot access that method at all, either from the parent or child class.

The compiler has no way of knowing that an instance of ComponentVisibility is actually a LeadComponentVisibility at compile-time, so you get the method not visible error. All of these checks are done at compile-time, not runtime, so the compiler has to determine if access should be allowed based on the data type at compile time. This is a limitation of a statically compiled, strongly typed language like Apex.

The only way to call the public version is to cast to an instance of LeadComponentVisibility. Note that within either class, the overridden method would be called if you passed in an instance of LeadComponentVisibility, but this is a runtime feature, not a compile-time feature, which is one of the main benefits of polymorphism.

3
  • So even if I instantiate LeadComponentVisibility in another class and call LeadComponentVisibility inherited methods it won't work? Is this how Protected is supposed to work? Not what I expected. For my second "Why?" I still don't understand. setRecordOwnerId is protected(so basically private), but when I do ComponentVisibility leadComponentVisibility = new LeadComponentVisibility(), isn't it polymorphism (dynamic binding)? Shouldn't I have access to setRecordOwnerId which is overriden and public?
    – nSv23
    Jul 7, 2020 at 17:51
  • @nSv23 I expanded my answer for you. Is that clearer?
    – sfdcfox
    Jul 7, 2020 at 18:06
  • thank you. It is more clear now.
    – nSv23
    Jul 7, 2020 at 20:08

You must log in to answer this question.

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