7

Can you make a global class virtual after it has been packaged?

Salesforce documentation states that:

You cannot add an abstract method to a global class after the class has been uploaded in a Managed - Released package version.

If the class in the Managed - Released package is virtual, the method that you can add to it must also be virtual and must have an implementation.

You cannot override a public or protected virtual method of a global class of an installed managed package.

However it doesn't cover whether it’s possible to make the class virtual. I would imagine it would also force me to make all existing global methods virtual as well (due to second sentence above).

9
+100

Empirical testing shows you can add the virtual class modifier to an already packaged global class with no side effects to the packaging process. What you can't do is then add a new method that isn't also marked as virtual.


Initial class:

global class GlobalTestClass {

    global string echo(string input) {
        return input + ' response';
    }
}

And its associated test case:

@IsTest
public class GlobalTestClass_Test {
    @IsTest
    public static void echoTest() {
        GlobalTestClass gtc = new GlobalTestClass();
        string response = gtc.echo('hello');
        System.assertEquals('hello response', response);
    }
}

Created v1 of the managed package - https://login.salesforce.com/packaging/installPackage.apexp?p0=04t280000011wZi

Updated global class -

global virtual class GlobalTestClass {

    global string echo(string input) {
        return input + ' response';
    }
}

Created v1.1 of the managed package - https://login.salesforce.com/packaging/installPackage.apexp?p0=04t280000011wZn

Updated global class again. Now with a virtual method as well:

global virtual class GlobalTestClass {

    global virtual string echo(string input) {
        return input + ' response';
    }
}

Create v1.2 of the managed package - https://login.salesforce.com/packaging/installPackage.apexp?p0=04t280000011wZx

What I can't do - add a new non-virtual method to the global class. The following fails:

global virtual class GlobalTestClass {

    global virtual string echo(string input) {
        return input + ' response';
    }

    global string echo2(string input2) {
        return input2;
    }
}

Cannot add new final methods to virtual or abstract classes: String namespace.GlobalTestClass.echo2(String)

  • I thought that accepting automatically awards the bounty. Apparently it does not, so I've corrected that. – ipavlic Oct 14 '17 at 17:58
  • I would love to know the reason you can't add final methods (and that includes promoting an existing public method to be global). This really screws you over if you found you need to promote visibility of an existing method that makes no sense to be virtual. :( – Phil W Mar 5 at 13:46
  • @PhilW The docs say that methods are final by default, so they don't need to keyword. As a guess I'd say the virtual requirement for new methods is related to existing Apex classes in subscribers that are extending the prior version of the global class. – Daniel Ballinger Mar 5 at 18:39
  • @DanielBallinger, I only said "can't add final methods" to reflect the wording in the documentation - yes, a non-virtual/non-abstract method is implicitly final. They (Salesforce) must have a very odd representation of an Apex class if adding a final method would mess up subscriber orgs. Adding a final method would not, in my mind, change any existing lookups (e.g. a virtual table) because it is not virtual. It is a new static symbol against the class, with an entirely new name. It should be trivial to handle and allow. – Phil W Mar 6 at 12:21

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.