4

So I have a class (B1) and an inner class (B1 again) in another class (A1).

public class A1 {

    public A1() { //constructor
        B1 obj = new B1();
    }

    public class B1 {
        public B1() { //constructor
            System.debug('inner class');
        }
    }
}

public class B1 {
    public B1() { //constructor
        System.debug('outer class');
    }
}

When I execute new A(); in anonymous window, I get inner class printed, but I need the instance of outer B1 class. One way to create the object of outer class is dynamic way with Type.forname, though I was wondering if there is any way to create the object in static manner. Like if we have a custom class Database, we can use System.Database for salesforce native class because of System namespace. Do we have something here?

2 Answers 2

3

No, you can't, because of Name Shadowing. Your only option is to rename one of the two classes (or, as you state, use Type.forName). There is no static syntax that allows accessing a top-level class from a different top-level class that has an inner class by the same name.

2
  • Interestingly, getting the Type statically still gives the inner class, but dynamic retrieval gets the proper token. Also interestingly, factory pattern does not help circumvent the issue.
    – Adrian Larson
    Commented Sep 3, 2021 at 15:00
  • @AdrianLarson Yeah, you have to end up using something like Callable to call the methods dynamically as well. It's a total mess.
    – sfdcfox
    Commented Sep 3, 2021 at 15:02
3

I strongly recommend you obviate the name shadowing entirely. But if you feel you absolutely must have it, and Type.forName does not work (for example if you lack a no-arg constructor), there is one workaround you could implement.

Putting a factory method within your top-level B1 class will not work. If you try to call it from A1, you get the following error:

Method does not exist or incorrect signature: void newInstance() from the type B1

You can, however, create a separate top level factory class to do your construction. This pattern would scale to an arbitrary number of construction signatures.

public class B1Factory
{
    public B1 newInstance()
    {
        return new B1();
    }
    public B1 newInstance(String someParameter)
    {
        return new B1(someParameter);
    }
}

Implementing this pattern would still add a lot of lines of code for little benefit compared to removing the name shadowing, but it does provide some workaround. As long as you don't also shadow the factory class, obviously

You must log in to answer this question.

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