8

We have a bunch of custom objects, some of which implement a specific set of custom fields of the same type. (e.g., UniqueID, ExternalID, etc.). I want to be able to write one method that takes and object and works with these fields without knowing (or caring) which object type it is. I know it is easily doable in Java but not sure how Apex allows this. So I want something like this:

public static void updateID(SObject myObject){
    myObject.uniqueID__c = myObject.externalID__c;
}
13

Mechanics

You need to use the get and put methods. Each method supports both String and SObjectField as the parameter type:

// terse
myObject.put('UniqueId__c', myObject.get('ExternalId__c'));

// verbose
SObjectField fieldToGet = MyObject__c.ExternalId__c;
SObjectField fieldToPut = MyObject__c.UniqueId__c;
Object value = myObject.get(fieldToGet);
myObject.put(fieldToPut, value);

Best Practice

There are many different scenarios under which you may want to use the dynamic methods get and put. How do you decide whether to use String or SObjectField?

SObjectField

Pros

  • Creates a hard-coded reference to the field.
  • If you try to delete the referenced field or change its API Name, the UI will prevent you from doing so!
    • In other words, this approach protects your code.

Cons

  • Syntax is somewhat more verbose. If you are really crunching up against the character limit, this style of reference might use more than you need.
    • There are probably better ways to shave characters.
  • You cannot pass cross-object references, like if you wanted to reference Account.Owner.Name from Opportunity.
    • You cannot call someOpportunity.get('Account.Owner.Name'), but you can combine getSObject and some string parsing to achieve the desired result.

String

Pros

  • More terse syntax allows you to write the same code in fewer characters.
  • Accepting this type as an input for your own method would allow you to support cross-object get calls (by incorporating getSObject).

Cons

  • Does not populate to the SymbolTable, meaning there is no programmatic connection anywhere between your code and the referenced field.
  • Because there is no programmatic connection, the system. will allow the field to be deleted or renamed (barring other blocking dependencies).
    • In other words, your code is vulnerable to configuration changes which might break it down the road.

Documentation

Both of the above are well covered in the Apex Developer Guide documentation for the SObject class. There are a few more signatures but you get the idea:

get(fieldName)
Returns the value for the field specified by fieldName, such as AccountNumber.

Signature

 public Object get(String fieldName)

Parameters

fieldName
Type: String

Return Value
Type: Object

Usage
For more information, see Dynamic SOQL.


put(fieldName, value)
Sets the value for the field specified by the field token Schema.sObjectField, such as, Schema.Account.AccountNumber and returns the previous value for the field.

Signature

public Object put(Schema.SObjectField fieldName, Object value)

Parameters

fieldName
Type: Schema.SObjectField

value
Type: Object

Return Value
Type: Object

  • The field token form should be preferred, because it prevents accidents from happening (e.g. renaming a field, misspelling a field, etc). – sfdcfox May 5 '17 at 15:33
  • @sfdcfox Depends what you're trying to support. If you want to support cross-object, you don't have a choice. – Adrian Larson May 5 '17 at 15:35
  • Yep. Just saying that one should prefer the object version when possible. I've seen far too many cases where developers went straight to using strings for everything, only to have one minor change by an unwitting admin break things. – sfdcfox May 5 '17 at 15:37

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.