Intermediate 20 min read

What Is an sObject?

By the end of this lesson, you'll be able to:

  • Explain what sObject means as the base type for every Salesforce record
  • Recognize that Account, Contact, and every custom object are all sObjects
  • Write a generic variable typed as sObject rather than a specific object type

Prerequisites: "Record IDs: 15 vs 18 Characters"

Every record type shares a common base

Account acc = new Account();
Contact con = new Contact();
Course_Enrollment__c enrollment = new Course_Enrollment__c();

sObject genericRecord1 = acc;         // valid — Account IS an sObject
sObject genericRecord2 = con;         // valid — Contact IS an sObject
sObject genericRecord3 = enrollment;  // valid — even custom objects ARE sObjects
  1. Account acc = new Account(); — a standard object.
  2. Contact con = new Contact(); — another standard object.
  3. Course_Enrollment__c enrollment = new Course_Enrollment__c(); — a custom object.
  4. (blank line)
  5. sObject genericRecord1 = acc; — this is Module 11's polymorphism ("is-a" relationships) applied at the platform level — valid because Account IS an sObject.
  6. sObject genericRecord2 = con; — valid — Contact IS an sObject too.
  7. sObject genericRecord3 = enrollment; — valid — even custom objects ARE sObjects. Every single Salesforce object, standard or custom, is fundamentally an sObject.

Why this matters: writing generic code

public void logRecordId(sObject record) {
    System.debug('Record Id: ' + record.Id);
}

logRecordId(new Account(Name = 'Acme Logistics'));
logRecordId(new Contact(LastName = 'Dlamini'));
  1. public void logRecordId(sObject record) { — accepts any kind of record — Account, Contact, or any custom object — without needing a separate overloaded version for each type.
  2. System.debug('Record Id: ' + record.Id); — because Id exists on every sObject.
  3. } — closes the method.
  4. (blank line)
  5. logRecordId(new Account(Name = 'Acme Logistics')); — passes an Account.
  6. logRecordId(new Contact(LastName = 'Dlamini')); — passes a Contact — the same method handles both. This is exactly Module 11's polymorphism, letting one method work uniformly across many concrete record types.

The trade-off: fewer specific fields available

sObject record = new Account(Name = 'Acme Logistics');
// record.Industry;  // compile error — sObject alone doesn't know about Industry
Account acc = (Account) record;
System.debug(acc.Industry); // fine, now typed specifically
  1. sObject record = new Account(Name = 'Acme Logistics'); — a generic sObject variable.
  2. // record.Industry; — commented out because this line would not compile — an sObject variable only exposes what's common to every record (like Id), not Account-specific fields.
  3. Account acc = (Account) record; — casting back to the specific type first.
  4. System.debug(acc.Industry); — now typed specifically, so Industry is accessible. This mirrors the trade-off from Module 11's polymorphism lesson: generality in exchange for giving up type-specific access until you cast back down.

Exercise

Write a method describeRecord(sObject record) that debugs the record's Id. Call it with both a new Account and a new Contact.

Show hint

Id exists on every sObject.

Salesforce: ○ Not connected Connect
APEX

Execution Results

Run your code to see the result.

What Is an sObject? Quiz

1. What is sObject?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

sObject is the base type every Salesforce record shares — Account, Contact, a custom object, all of them are sObjects underneath, which is what makes generic, type-agnostic Apex code possible.