4

I am confused about what is happening in a small section of some code. I have a class that has a wrapper class inside it. There is an external class that calls this wrapper class Models.add(new CheckItemsClass(...)) The part that confuses me is that the Models.cls does not have any reference or instance of CheckItemsClass. So how are we able to add a new CheckItemsClass to the Models.cls?

public class ChecklistController{
    public List<CheckItemClass> fillItems(Credit_review__c obj){
        Models.add(new CheckItemClass('Miscellaneous (Google Search Items)',obj.GIS_Stip_Notes_Miscellaneous_Search__c,obj.GIS_Stip_Miscellaneous_Search__c));
        return Models;
    }
    public class CheckItemClass{
        public string item {get;set;}
        public string notes {get;set;}
        public boolean flag {get;set;}
        public CheckItemClass(string i,string n,boolean f){
           this.item = i;
           this.notes = n;
           this.flag = f;
        }
    }
}

public without sharing class Models {
    public static void mdlEncinitas(List<WC_Credit_Decision__c> wcObs){...}
    public static void mdlDataV1(List<WC_Credit_Decision__c> wcObs, List<ID> wccdIds) {...}
    public static void mdlDataV2(List<WC_Credit_Decision__c> wcObs, List<ID> wccdIds) {...}
    public static void mdlEncinitasRecommender(WC_Credit_Decision__c wcOb, Integer score10pt, Integer score, String productionChannel, Double grossSalesRunRate, Double judgmentTotalAmt, Integer maxTib, Double avgOfAvgDailyBal, Double bkDateYrs, Integer maxFICO, String sicCode, NF_SIC_4__c sicOb, Credit_Review__c crOb, WC_Buy_Rate__c brOb, Boolean lenderMissing, Double maxNegDaysLst3Mnths, String oppType, List<Decision_Attribute__c> decisionAttr, Double maxNegDaysEver, Double maxNSFsEver) {...}
    public static void mdlEncinitasRun(ID wcId, WC_Credit_Decision__c wcOb, Credit_Review__c crOb, Opportunity oppOb, List<Monthly_Review__c> mrObs,NF_SIC_4__c sicOb, Account acctOb, WC_Buy_Rate__c brOb, Boolean brokerMissing, Map<Id,List<Credit_Review_Monthly_Ledger__c>> CR_ledgers_map, List<Decision_Attribute__c> decisionAttr){...}
}
0

3 Answers 3

6

Somewhere else in the local context, there is a variable declaration that's shadowing the class Models.

Example:

public class TestQ242685 {
    public class InnerClass {

    }

    public static void runTest() {
        List<InnerClass> SomeOtherClass = new List<InnerClass>();

        SomeOtherClass.add(new InnerClass());
        System.debug(SomeOtherClass);
    }
}

public class SomeOtherClass {
    // No `add()` method!
}

Call TestQ242685.runTest() and sure enough, you'll see

16:04:08:034 USER_DEBUG [10]|DEBUG|(InnerClass:[])

You've got a List<CheckItemClass> Models declared somewhere.

1
  • ah you are right, it was at the very top. I totally missed it. thank you!
    – Olivia
    Commented Dec 14, 2018 at 21:11
5

You seem to have a name shadowing here.

This code is adding CheckItemClass objects in a List<CheckItemClass> which is most likely declared in your controller as:

List<CheckItemClass> Models = new List<CheckItemClass>();`

And from documentation:

In particular it is legal for a variable, method, and a class within a class to have the same name.

So that's why you are not getting any compile errors with same names. It's always a good idea to keep names specific to the context.

And it's the same variable that's being used in your fillItems() method as below:

public List<CheckItemClass> fillItems(Credit_review__c obj){
    Models.add(new CheckItemClass('Miscellaneous (Google Search Items)',obj.GIS_Stip_Notes_Miscellaneous_Search__c,obj.GIS_Stip_Miscellaneous_Search__c));
    return Models;
}

So Models.add() is not really calling any method in the Models class, but the List.add() method. Also refer to the return statement which confirms as what you are returning.

1
  • thank you! I realized I missed the List<CheckItemClass> Models = new List<CheckItemClass>();. This is a good example of how important naming is. It can get easily confusing!
    – Olivia
    Commented Dec 14, 2018 at 21:11
3

Name shadowing can take many forms...

Here is my personal favorite (as I have made this mistake more than once wrto name shadowing) from the lazy loading pattern...

public Contact[] contacts {
  get {
    if (contacts == null) {
       Contact[] contacts = [SELECT ... FROM Contact WHERE ...]; //oops - declared new vbl!
    }
    return contacts;
  } private set;
}

if (contacts.isEmpty()) {...} . // null pointer exception!

You must log in to answer this question.

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