12

When I create a class called Process it looks like I'm experiencing class shadowing. For example:

public class Process {
    //...
}

The existence of the above class prevents me implementing the Process.Plugin interface. While it isn't a reserved word, here's an example class that I might attempt to save:

public class MyPlugin implements Process.Plugin {
    public Process.PluginDescribeResult describe() {
        return null;
    }

    public Process.PluginResult invoke(Process.PluginRequest request) {
        return null;
    }
}

and I'm immediately hit with the following compile error message:

Invalid type: Process.Plugin

At this point I'd thought this was a similar situation to creating a class called Account or some other SObject name. When that happens, you can fully qualify Schema.Account to differentiate them.

But it seems Process.Plugin is already fully qualified; System.Process.Plugin isn't a valid type.

Is there any way I can have a class called Process in my org and still use Process.Plugin?

3 Answers 3

9

I agree with @ca_peterson. There is no way to do it. The Type Resolution documentation indicates the parser will look for an inner type on a class as it has precedence over a top-level class in a namespace (see last line of the doc quoted below). In your case, the parser would not find an inner type "Plugin" defined on your "Process" class, resulting in the "Invalid type" error.

Because the type system must resolve user-defined types defined locally or in other classes, the Apex parser evaluates types as follows:

  1. For a type reference TypeN, the parser first looks up that type as a scalar type.
  2. If TypeN is not found, the parser looks up locally defined types.
  3. If TypeN still is not found, the parser looks up a class of that name.
  4. If TypeN still is not found, the parser looks up system types such as sObjects.

For the type T1.T2 this could mean an inner type T2 in a top-level class T1, or it could mean a top-level class T2 in the namespace T1 (in that order of precedence).

0
11

This is a rather interesting situation since according to the docs Process is not the outer class but the namespace itself. Since you're not just shadowing a class name but instead an entire namespace I'm not sure there's a way around this; in fact I strongly doubt that there is.

1
  • Aha, a namespace and not a class... interesting Apr 4, 2014 at 3:48
3

TL;DR I have made a simple test for Managed Package case, and it seems that shadowing doesn't cross managed package boundary. Even if there is a class on org that is shadowing one of the Salesforce classes, managed code works well.

But if shadowed classes exist before package installation, the installation will fail for these classes (during the deployment phase).


What I have tested?

  1. I package the code shown below.
  2. Install package on new scratch org.
  3. Insert Account record and check if Opportunity was created. (success)
  4. Create new Database.cls class on scratch org.
  5. Insert Account record and check if Opportunity was created. (success)
  6. Create Accounts.cls class directly on scratch org. (failed, due to shadowing).

As we can see even if the Database class was shadowed on org, it doesn't shadow the classes used in Managed Packages.

But if shadowed classes exist before package installation, the installation will fail for these classes (during the deployment phase).

References

Accounts.cls

public with sharing class Accounts {
    public static void databaseOperation() {
        Database.insert(new Opportunity(Name = 'databaseOperation', StageName = 'Open', CloseDate = Date.today()));
    }
}

AccountTrigger.trigger

trigger AccountTrigger on Account(after insert, after update) {
    if (Trigger.isAfter) {
        if (Trigger.isInsert) {
            Accounts.databaseOperation();
        }
    }
}
2
  • Managed package classes may exist prior to new SF class names so this is useful. Thank you Jan 11, 2023 at 11:08
  • You are welcome @MattandNeil. Please look at my update regarding what will happen when the shadowed class already exists in org before the package installation. Just updated the post.
    – Mateusz B
    Jan 11, 2023 at 12:22

You must log in to answer this question.

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