C#/Java Developers often strive to apply common coding practices when working with Salesforce Apex. One crucial coding feature involves utilizing object initializers to initialize class properties while creating and initializing objects. It’s worth noting that Salesforce supports object initializers exclusively for sObjects and not for custom classes. This article will demonstrate how to implement Object Initializers in Salesforce Apex.
Object Initializers provide a method for assigning property values during object creation without the need for constructor calls.
What makes object initializers essential in Salesforce?
In Apex classes, we often define numerous fields or properties to enhance the business functionality of the class. Prior to using any class method, it’s necessary to either assign these properties individually, as shown below, or pass all the required properties as method parameters.
AddressService addService=new addService(); zip.ZipCode='10011'; zip.Address1='47 W 13th St'; zip.Address2=''; zip.State='NY'; zip.City='New York'; zip.verifyAddress();
This code functions without any issues, but the property assignments are carried out across multiple lines, resulting in multiple execution steps. It would be advantageous to have a method for assigning all class properties using a single statement.
It’s important to note that Salesforce doesn’t provide support for object initializers for custom classes. This article will present an alternative approach to achieve a similar concept. While the execution will still span multiple lines as values are assigned one by one in the class constructor, the benefit lies in the cleaner and more maintainable code achieved by enabling single-line assignments during object creation.
In line with good coding practices, it’s advisable to limit the number of parameters to a maximum of three. Excessive parameters can lead to an accumulation of functionality within a single method. Therefore, it is preferable to use fewer parameters and create smaller methods, contributing to more maintainable code. Let’s explore how we can apply the object initializer concept in Apex.
1.sObject Initialization
Salesforce Apex facilitates sObject initialization, allowing us to set properties during object creation. For example, if we wish to create a feed item record, we can employ the following code, which utilizes an object initializer.
FeedItem objPost=new FeedItem( IsRichText=true, ParentId = '0012v00003JMBTqAAP', Body = 'Hello there from <b>SalesforceCodex.com</b>' ); insert objPost;
Likewise, we can employ an object initializer for custom objects too. In the following instance, I am utilizing the custom object CodeCoverage__c to set field values during initialization.
CodeCoverage__c code=new CodeCoverage__c( ApexClassOrTriggerName__c='0012v00003JMBTqAAP', PercentCovered__c=10 ); insert code;
2. Apex Class Initializer
We design classes to provide tailored solutions for specific business needs that cannot be met through standard functionalities. We continuously incorporate new classes to meet these unique requirements. To ensure best practices, it’s advisable to employ Object-Oriented Principles (OOPs) in our Apex code. When applying OOPs concepts, we need to create instances of classes for utilization. In Salesforce Apex, there is a constraint preventing us from employing an object initializer for instantiation.
Now, let’s explore how we can achieve object initialization behavior. Consider the following Apex class, HttpCall.
public class HTTPCall { public string endPointUrl{get;set;} public string method{get;set;} public string userName{get;set;} public string password{get;set;} public integer timeOutDuration{get;set;} public string body{get;set;} }
We will employ the provided code to create instances of this class in order to enable third-party integration.
HTTPCall call=new HttpCall( EndPoint='https://api.google.com/voice/search', Method='Get' );
When we run the above code it will throw an error
Invalid constructor syntax, name=value pairs can only be used for SObjects: HTTPCall |
This error shows that we can not initialize objects similar to sObject initializer. Now let us solve this error by creating a constructor.
Create Constructor
We have the option to establish a constructor for initializing object attributes. We can include various parameters to initialize each property individually. Furthermore, constructor overloading can be employed to instantiate different combinations of properties.
public class HTTPCall { public string endPointUrl{get;set;} public string method{get;set;} public string userName{get;set;} public string password{get;set;} public integer timeOutDuration{get;set;} public string body{get;set;} public HTTPCall(string endPoint,string method, string body) { endPointUrl=endPoint; method=method; } public HTTPCall(string endPoint,string method,string userName, string password, string body) { endPointUrl=endPoint; method=method; } }
We can now instantiate objects using the below code.
//First Constructor Called HTTPCall call=new HttpCall('https://api.google.com/voice/search','Get','{"customers":{"firstName": "Joe”,"lastName": “Bloggs”}}'); //Second Constructor Called HTTPCall call=new HttpCall('https://api.google.com/voice/search','Get','userName','Password','{"customers":{"firstName": "Joe”,"lastName": “Bloggs”}}');
The code logic is correct and we will not get any issues while running. We will find the issue when we run Apex PMD for code analysis. We will get the below warning for the second constructor as a maximum of 3 parameters is good for best code practice.
Avoid long parameter lists (rule: Design-ExcessiveParameterList)
Let us resolve this warning using the second approach of creating a constructor.
Constructor with Map parameters
In this approach, we will use the Map object to create a collection and pass it to the constructor. We can pass primitive, derived, or object data types as well.
public class HTTPCall { public string endPointUrl{get;set;} public string method{get;set;} public string userName{get;set;} public string password{get;set;} public integer timeOutDuration{get;set;} public string body{get;set;} public HTTPCall(string endPoint,string method, string body) { endPointUrl=endPoint; method=method; } public HTTPCall(Map<String, string> initMap) { endPointUrl = initMap.get('endPoint'); method = initMap.get('method'); userName = initMap.get('userName'); password = initMap.get('password'); body = initMap.get('body'); } }
We will call the second constructor like below to initialize properties.
Map<String, String> initMap=new Map<String, String>{ 'endPointUrl' => 'https://api.google.com/voice/search', 'method' => 'GET', 'userName' => 'username', 'password'=>'password', 'body'=>'{"customers":{"firstName": "Joe”,"lastName": “Bloggs”}}' }; HTTPCall call=new HTTPCall(initMap);
This map initializer can also be utilized within a method to transmit multiple parameters.
Need to discuss the topic
If you want to discuss further on this topic or any other Salesforce topic, please ping me on my LinkedIn profile.