Type Casting in Apex
Hello devs,
What are Upcasting and Downcasting? How can you cast Apex Map, List, and Set? What is a supertype, and what is the difference between SObject and Object? Answers to these questions and much more can be found in this post!
Let’s begin.
Before We Start
I am using different emojis to grab your attention:
- ๐จ – Unexpected casting behavior.
- โ – Code that works.
- โ – Code that does not work.
Supertype
What supertype is?
A supertype is an abstract/virtual class or an interface that is used by a child class.
e.g.
Interface
public interface Parent {
void display();
}
public class Child implements Parent {
public void display() {
System.debug('Hello Parent Interface!');
}
}
The Parent
interface is a supertype for the Child
class.
A class can implements
many interfaces, meaning that a class can have many supertypes.
Abstract
public abstract Parent {
abstract void display();
}
public class Child extends Parent {
public override void display() {
System.debug('Hello Parent Abstract Class!');
}
}
The Parent
abstract class is a supertype/superclass for the Child
class.
A class can extends
only one abstract class, but it can still implements
many interfaces.
Virtual
public virtual Parent {
virtual void display() {
System.debug('Hello From Parent Virtual Class!');
}
}
public class Child extends Parent {
public override void display() {
System.debug('Hello Parent Virtual Class!');
}
}
The Parent
virtual class is a supertype/superclass for the Child
class.
A class can extends
only one virtual class, but it can still implements
many interfaces.
Upcasting vs Downcasting
You know what supertype is, it’s necessary to understand the difference between Upcasting and Downcasting.
Reference
To better understand upcasting and downcasting, we need some examples.
We have two classes (it can be also class and interface), Parent
and Child
.
Parent
is avirtual
class and has avirtual
method.Child
extends theParent
class and override thevirtual
method.
If you don’t understand what virtual
means, you can refer to the Abstract, Virtual, Interface in Apex post.
public virtual class Parent {
public String parentProperty;
public virtual void display() {
System.debug('Method from Parent');
}
}
public class Child extends Parent {
public String childProperty;
public override void display() {
System.debug('Method from Child');
}
public void childMethod() {
System.debug('Child secret method');
}
}
Parent parent = new Parent();
parent.parentProperty = 'Parent Property Test';
parent.display();
// 'Method from Parent'
Child child = new Child();
child.childProperty = 'Parent Property Test';
child.childMethod();
// 'Child secret method'
child.display();
// 'Method from Child'
Upcasting
Child
extends theParent
class. It means thatParent
is a supertype/superclass forChild
. Because of this, the following syntax:Parent parent = new Child();
is valid.- Casting a subclass (
Child
) to a supertype/superclass (Parent
) is called Upcasting. - Upcasting can be either explicit or implicit.
Implicit Upcasting
Upcasting can be done implicitly.
โ
Parent parent = new Child();
Explicit Upcasting
Code should be as simple as possible (KISS rule), so the better approach is to use implicit upcasting.
โ โ
Parent parent = (Parent) new Child();
Access
Parent parent = new Child();
parent.childProperty = 'Child Property Test';
// Variable does not exist: childProperty
parent.childMethod();
// Method does not exist or incorrect signature: void childMethod() from the type Parent
The parent
variable has access to:
Parent
public variables.Parent
public methods.Child
ONLY overriden methods.
Downcasting
- Casting a supertype/superclass (
Parent
) to a subclass (Child
) is called Downcasting. - Upcasting can be done ONLY explicitly.
Implicit Downcasting
Downcasting CANNOT be implicit. Why?
- There can be many children of the
Parent
class. e.gpublic class Child2 extends Parent { ... }
. - Apex needs to know to what type the variable should be cast to.
โ
Parent parent = new Child();
Child child = parent;
// Illegal assignment from Parent to Child
Explicit Downcasting
You have to cast explicitly (Child)
so the compiler checks in the background if this type of casting is possible or not. If not, you will get System.TypeException: Invalid conversion from runtime type Parent to Child
.
โ
Parent parent = new Parent();
Child child = (Child) parent;
// System.TypeException: Invalid conversion from runtime type Parent to Child
โ
Parent parent = new Child();
Child child = (Child) parent;
child.parentProperty = 'Parent Property Test';
child.childProperty = 'Child Property Test';
child.display();
// 'Method from Child'
Access
The child
variable has access to:
Parent
public variables.Parent
public methods.Child
ALL public methods and variables.
SObject
SObject
is a supertype for:
- all standard objects (Account, Contact, etc.)
- all custom objects (MyCustomObject__c)
โ
SObject account = new Account(Name = 'My Account');
SObject myObject = new MyCustomObject__c();
Object
Object
is a supertype for:
- all standard objects
- all custom objects
- all apex classes
- all collections (List, Set and Map)
- all apex types (Integer, String, Boolean)
โ
Object account = new Account(Name = 'Test Account');
Object myObject = new MyCustomObject__c();
Object myClass = new MyClass();
Object myList = new List<String>();
Object myName = 'Beyond The Cloud';
Methods inherited from Object class
toString()
public class A {}
System.debug(new A().toString()); // A:[]
public class A {
public override String toString() {
return 'Hello toString()';
}
}
System.debug(new A().toString()); // 'Hello toString()'
equals()
public class A {}
System.debug(new A().equal('Some String')); // false
hashCode()
public class A {}
System.debug(new A().hashCode()); // 2069582068
System.debug('Some String'.hashCode()); // 2147069117
clone()
public class A {}
System.debug(new A().clone());
SObject and Object
SObject and Object – instanceOf
Assert.isTrue(new Contact() instanceOf Object);
// Operation instanceOf is always true since an instance of Contact is always an instance of Object
Assert.isTrue(new Account() instanceOf Object);
// Operation instanceOf is always true since an instance of Account is always an instance of Object
SObject contact = new Contact();
Assert.isTrue(contact instanceOf Object);
// Operation instanceOf is always true since an instance of SObject is always an instance of Object
Expression | is instanceOf |
---|---|
SObject instanceOf Object |
TRUE โ |
SObject
is an instance ofObject
.Object
is a supertype forSObject
.
SObject and Object – casting
Object to SObject
Downcasting
Object
needs to be explicitly cast toSObject
.
Why?
Object
is a supertype ofSObject
.- Conversion from
Object
toSObject
is called Downcasting. - As you already know from Downcasting section. Downcasting needs to be explicit
(SObject)
.
โ
// Implicit downcasting
Object objectContact = new Contact();
SObject sObjectContact = objectContact;
// Illegal assignment from Object to SObject
โ
// Explicit downcasting
Object objectContact = new Contact();
SObject sObjectContact = (SObject) objectContact;
SObject to Object
Upcasting
SObject
can be explicitly or implicitly cast toObject
.
Why?
Object
is a supertype ofSObject
.- Conversion from
SObject
toObject
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
โ
// Explicit upcasting
SObject sobjectAccount = new Account();
Object objectAccount = sobjectAccount;
Inherited methods
- Interestingly,
Object
is a supertype forSObject
, butSObject
does NOT inheritObject
methods liketoString(), equals(), hashCode(), clone()
.
SObject
has all of the following methods SObject class methods..
โ
SObject sObjectAccount = new Account();
System.debug(sObjectAccount.toString());
// Method does not exist or incorrect signature: void toString() from the type SObject
โ
Object objectAccount = new Account();
System.debug(objectAccount.toString());
// Account:{}
However, all Apex Classes inherit Object
methods (toString()
, equals()
, hashCode()
, clone()
).
โ
Parent parent = new Parent();
System.debug(parent.toString());
// Parent:[parentProperty=null]
System.debug(parent.equals('SomeValue'));
// false
System.debug(parent.hashCode());
// 296136299
System.debug(parent.clone());
// Parent:[parentProperty=null]
Standard/Custom Object
Standard/Custom Object – instanceOf
Assert.isTrue(new Account() instanceOf SObject);
// Operation instanceOf is always true since an instance of Account is always an instance of SObject
Assert.isTrue(new Account() instanceOf Object);
// Operation instanceOf is always true since an instance of Account is always an instance of Object
Expression | is instanceOf |
---|---|
Standard/Custom Object instanceOf SObject |
TRUE โ |
Standard/Custom Object instanceOf SObject |
TRUE โ |
Standard/Custom Object instanceOf Object |
TRUE โ |
Standard/Custom Object
is an instance ofSObject
andObject
.SObject
andObject
are supertypes forStandard/Custom Objects
.
Standard/Custom Object to SObject – casting
Standard/Custom Object to SObject
Upcasting
Why it works?
SObject
is a supertype forAccount
,Contact
, and other standard or custom objects.- Conversion from
Standard/Custom Object
toSObject
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
โ
// Implicit upcasting
Account account = new Account(Name = 'My Account');
SObject myAccount = account;
SObject to Standard/Custom Object
Downcasting
Why it works?
SObject
is a supertype forAccount
,Contact
, and other standard or custom objects.- Conversion
SObject
toStandard/Custom Object
is called Downcasting. - As you already know from Downcasting section. Downcasting can be done ONLY explicitly.
โ
// Explicit downcasting
SObject account = new Account(Name = 'My Account');
Account myAccount = (Account) account;
Standard/Custom Object to Object – casting
Standard/Custom Object to Object
Upcasting
Why it works?
Object
is a supertype forAccount
,Contact
, and other standard or custom objects.- Conversion from
Standard/Custom Object
toObject
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
โ
// Implicit upcasting
Account account = new Account(Name = 'My Account');
Object myAccount = account;
Object to Standard/Custom Object
Downcasting
Why it works?
Object
is a supertype forAccount
,Contact
, and other standard or custom objects.- Conversion
Object
toStandard/Custom Object
is called Downcasting. - As you already know from Downcasting section. Downcasting can be done ONLY explicitly.
โ
// Explicit downcasting
Object account = new Account(Name = 'My Account');
Account myAccount = (Account) account;
Primitive Types
Primitive Types – instanceOf
Blob myBlob = Blob.valueof('StringToBlob');
Assert.isTrue(myBlob instanceOf Object);
// Operation instanceOf is always true since an instance of Blob is always an instance of Object
Boolean myBoolean = true;
Assert.isTrue(myBoolean instanceOf Object);
// Operation instanceOf is always true since an instance of Boolean is always an instance of Object
Date myDate = Date.today();
Assert.isTrue(myDate instanceOf Object);
// Operation instanceOf is always true since an instance of Date is always an instance of Object
DateTime myDateTime = DateTime.now();
Assert.isTrue(myDateTime instanceOf Object);
// Operation instanceOf is always true since an instance of Datetime is always an instance of Object
Decimal myDecimal = 1.1;
Assert.isTrue(myDecimal instanceOf Object);
// Operation instanceOf is always true since an instance of Decimal is always an instance of Object
Double myDouble = 1261992;
Assert.isTrue(myDouble instanceOf Object);
// Operation instanceOf is always true since an instance of Double is always an instance of Object
Id myId = '1035U00000ckdinQAX';
Assert.isTrue(myId instanceOf Object);
// Operation instanceOf is always true since an instance of Id is always an instance of Object
Integer myInteger = 12345;
Assert.isTrue(myInteger instanceOf Object);
// Operation instanceOf is always true since an instance of Integer is always an instance of Object
Long myLong = 4271990;
Assert.isTrue(myLong instanceOf Object);
// Operation instanceOf is always true since an instance of Long is always an instance of Object
String myString = 'myString';
Assert.isTrue(myString instanceOf Object);
// Operation instanceOf is always true since an instance of String is always an instance of Object
Account account = new Account();
Assert.isTrue(account instanceOf Object);
// Operation instanceOf is always true since an instance of Account is always an instance of Object
SObject account = new Account();
Assert.isTrue(account instanceOf Object);
// Operation instanceOf is always true since an instance of SObject is always an instance of Object
Expression | is instanceOf |
---|---|
Blob instanceOf Object |
TRUE โ |
Boolean instanceOf Object |
TRUE โ |
Date instanceOf Object |
TRUE โ |
Datetime instanceOf Object |
TRUE โ |
Decimal instanceOf Object |
TRUE โ |
Double instanceOf Object |
TRUE โ |
Id instanceOf Object |
TRUE โ |
Integer instanceOf Object |
TRUE โ |
Long instanceOf Object |
TRUE โ |
String instanceOf Object |
TRUE โ |
Account instanceOf Object |
TRUE โ |
SObject instanceOf Object |
TRUE โ |
- All Primitive Data Types are
instanceOf
Object
class. Object
is a supertype for all primitve types.
Primitive Types – casting
Upcasting
Primitive Types
can be implicilty cast toObject
.
Why?
Object
is a supertype of all Primitive Types.- Conversion from
Primitive Type
toObject
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
โ
Blob myBlob = Blob.valueof('StringToBlob');
Object myBlobResult = myBlob;
Boolean myBoolean = true;
Object myBooleanResult = myBoolean;
Date myDate = Date.today();
Object myDateResult = myDate;
DateTime myDateTime = DateTime.now();
Object myDateTimeResult = myDateTime;
Decimal myDecimal = 1.1;
Object myDecimalResult = myDecimal;
Double myDouble = 1261992;
Object myDoubleResult = myDouble;
Id myId = '1035U00000ckdinQAX';
Object myIdResult = myId;
Integer myInteger = 12345;
Object myIntegerResult = myInteger;
Long myLong = 4271990;
Object myLongResult = myLong;
String myString = 'myString';
Object myStringResult = myString;
Account account = new Account();
Object myAccountResult = account;
List
List<SObject>
List<SObject>
– instanceOf
Assert.isTrue(new List<Account>() instanceOf List<SObject>);
// Operation instanceOf is always true since an instance of List<Account> is always an instance of List<SObject>
Assert.isTrue(new List<SObject>() instanceOf List<Account>);
// Works
Assert.isTrue(new List<SObject>() instanceOf List<Object>);
// Operation instanceOf is always false since an instance of List<SObject> is never an instance of List<Object>
Expression | is instanceOf |
---|---|
List<Standard/CustomObject> instanceOf List<SObject> |
TRUE โ |
List<SObject> instanceOf List<Standard/CustomObject> |
TRUE โ |
List<SObject> instanceOf List<Object> |
FALSE โ |
๐จ
List<SObject>
is an instance of concreteStandard/Custom
Object!List<SObject>
is NOT an instance ofList<Object>
.
List<SObject>
– casting
List<SObject>
to List<Object>
โ
List<SObject> myAccounts = new List<SObject>{ new Account() };
List<Object> myAccountResults = myAccounts;
๐จ
List<SObject>
is NOT an instance ofList<Object>
(based oninstanceOf
), but you can still assignList<SObject>
toList<Object>
. Do not trustinstanceOf
!
List<Standard/Custom>
to List<SObject>
Upcasting
Why it works?
List<SObject>
is a supertype forList<Standard/Custom>
.- Conversion from
Standard/Custom
Object toList<SObject>
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
โ
List<Account> accounts = new List<Account>();
List<SObject> myAccounts = accounts;
List<SObject>
to List<Standard/Custom>
Upcasting/Downcasting (?)
๐จ
List<Standard/CustomObject>
is an instance ofList<SObject>
, andList<SObject>
is an instance ofList<Standard/CustomObject>
.List<Standard/CustomObject>
is a supertype forList<SObject>
, andList<SObject>
is a supertype forList<Standard/CustomObject>
.- You can do implicit casting.
โ
List<SObject> accounts = new List<Account>();
List<Account> myAccounts = accounts;
List<SObject> accounts = new List<SObject>();
List<Account> myAccounts = accounts;
List<Object>
List<Object>
– instanceOf
Assert.isTrue(new List<Blob>{ Blob.valueof('StringToBlob') } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Blob>
Assert.isTrue(new List<Boolean>{ true } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Boolean>
Assert.isTrue(new List<Date>{ Date.today() } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Date>
Assert.isTrue(new List<DateTime>{ DateTime.now() } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<DateTime>
Assert.isTrue(new List<Decimal>{ 1.1 } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Decimal>
Assert.isTrue(new List<Double>{ 1261992 } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Double>
Assert.isTrue(new List<Integer>{ 12345 } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Integer>
Assert.isTrue(new List<Long>{ 4271990 } instanceOf List<Object>);
// Operation instanceOf is always true since an instance of List<Blob> is always an instance of List<Long>
Assert.isTrue(new List<SObject>() instanceOf List<Object>);
// Operation instanceOf is always false since an instance of List<SObject> is never an instance of List<Object>
Expression | is instanceOf |
---|---|
List<Blob> instanceOf List<Object> |
TRUE โ |
List<Boolean> instanceOf List<Object> |
TRUE โ |
List<Date> instanceOf List<Object> |
TRUE โ |
List<Datetime> instanceOf List<Object> |
TRUE โ |
List<Decimal> instanceOf List<Object> |
TRUE โ |
List<Double> instanceOf List<Object> |
TRUE โ |
List<Id> instanceOf List<Object> |
TRUE โ |
List<Integer> instanceOf List<Object> |
TRUE โ |
List<Long> instanceOf List<Object> |
TRUE โ |
List<String> instanceOf List<Object> |
TRUE โ |
List<SObject> instanceOf List<Object> |
FALSE โ |
๐จ
SObject
is always an instance ofObject
, hoveverList<SObject>
is NOT an instance ofList<Object>
.
List<Object>
– casting
- We can cast
List<ConcreteType>
toList<Object>
,
Why?
List<Object>
is a supertype ofList<ConcreteType>
.- Conversion from
List<ConcreteType>
toList<Object>
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
- There is no need to cast explicitly by adding
(List<Object>)
.
List<Blob> myBlobs = new List<Blob>{ Blob.valueof('StringToBlob') };
List<Object> myBlobResult = myBlobs;
List<Boolean> myBooleans = new List<Boolean>{ true };
List<Object> myBooleanResult = myBooleans;
List<Date> myDates = new List<Date>{ Date.today() };
List<Object> myDateResult = myDates;
List<DateTime> myDateTimes = new List<DateTime>{ DateTime.now() };
List<Object> myDateTimeResult = myDateTimes;
List<Decimal> myDecimals = new List<Decimal>{ 1.1 };
List<Object> myDecimalResult = myDecimals;
List<Double> myDoubles = new List<Double>{ 1261992 };
List<Object> myDoubleResult = myDoubles;
List<Integer> myIntegers = new List<Integer>{ 12345 };
List<Object> myIntegerResult = myIntegers;
List<Long> myLongs = new List<Long>{ 4271990 };
List<Object> myLongResult = myLongs;
List<String> myStrings = new List<String>{ 'myString' };
List<Object> myStringResult = myStrings;
List<SObject> myAccounts = new List<SObject>{ new Account() };
List<Object> myAccountResults = myAccounts;
๐จ
List<SObject>
is NOT an instance ofList<Object>
(based oninstanceOf
), but you can still assignList<SObject>
toList<Object>
.
List Summary
List casting in Apex is a bit unusual.
What is common:
List<ConcreteType>
is an instance ofList<Object>
.List<Object>
is a supertype forList<ConcreteType>
.
What is unexpected:
- Based on
instanceOf
.List<SObject>
is not an instance ofList<Object>
, but you can still assignList<SObject>
toList<Object>
. - You can even assign
List<SObject>
toList<Object>
. Do not trustinstanceOf
! - Even more unexpectedly,
List<SObject>
is an instance of concreteList<Standard/Custom>
Object!
Set
Set<SObject>
Set<SObject>
– instanceOf
Assert.isTrue(new Set<Account>() instanceOf Set<SObject>);
//Operation instanceOf is always false since an instance of Set<Account> is never an instance of Set<SObject>
Assert.isTrue(new Set<SObject>() instanceOf Set<Account>);
// Operation instanceOf is always false since an instance of Set<SObject> is never an instance of Set<Account>
Assert.isTrue(new Set<SObject>() instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<SObject> is never an instance of Set<Object>
Expression | is instanceOf |
---|---|
Set<Standard/CustomObject> instanceOf Set<SObject> |
FALSE โ |
Set<SObject> instanceOf Set<Standard/CustomObject> |
FALSE โ |
Set<SObject> instanceOf Set<Object> |
FALSE โ |
๐จ
Set<Standard/CustomObject>
is NOT an instance ofSet<SObject>
.
Set<SObject>
– casting
Set<SObject>
to Set<Object>
- You CANNOT cast
Set<SObject>
toSet<Object>
โ
Set<SObject> myAccounts = new Set<SObject>{ new Account() };
Set<Object> myAccountResults = myAccounts;
// Illegal assignment from Set<SObject> to Set<Object>
Set<SObject> myAccounts = new Set<SObject>{ new Account() };
Set<Object> myAccountResults = (Set<SObject>) myAccounts;
// Illegal assignment from Set<SObject> to Set<Object>
Set<Standard/Custom>
to Set<SObject>
- You CANNOT cast
Set<Standard/Custom>
toSet<SObject>
โ
Set<Account> accounts = new Set<Account>();
Set<SObject> myAccounts = accounts;
// Illegal assignment from Set<Account> to Set<SObject>
Set<Account> accounts = new Set<Account>();
Set<SObject> myAccounts = (Set<Account>) accounts;
// Illegal assignment from Set<Account> to Set<SObject>
Set<SObject>
to Set<Standard/Custom>
- You CANNOT cast
Set<SObject>
toSet<Standard/Custom>
โ
Set<SObject> accounts = new Set<Account>();
// Illegal assignment from Set<Account> to Set<SObject>
Set<SObject> accounts = new Set<SObject>();
Set<Account> myAccounts = accounts;
// Illegal assignment from Set<SObject> to Set<Account>
Set<Object>
Set<Object>
– instanceOf
Assert.isTrue(new Set<Blob>{ Blob.valueof('StringToBlob') } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Blob> is never an instance of Set<Object>
Assert.isTrue(new Set<Boolean>{ true } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Boolean> is never an instance of Set<Object>
Assert.isTrue(new Set<Date>{ Date.today() } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Date> is never an instance of Set<Object>
Assert.isTrue(new Set<DateTime>{ DateTime.now() } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<DateTime> is never an instance of Set<Object>
Assert.isTrue(new Set<Decimal>{ 1.1 } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Decimal> is never an instance of Set<Object>
Assert.isTrue(new Set<Double>{ 1261992 } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Double> is never an instance of Set<Object>
Assert.isTrue(new Set<Integer>{ 12345 } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Integer> is never an instance of Set<Object>
Assert.isTrue(new Set<Long>{ 4271990 } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<Long> is never an instance of Set<Object>
Assert.isTrue(new Set<String>{ 'myString' } instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<String> is never an instance of Set<Object>
Assert.isTrue(new Set<SObject>() instanceOf Set<Object>);
// Operation instanceOf is always false since an instance of Set<SObject> is never an instance of Set<Object>
Expression | is instanceOf |
---|---|
Set<Blob> instanceOf Set<Object> |
FALSE โ |
Set<Boolean> instanceOf Set<Object> |
FALSE โ |
Set<Date> instanceOf Set<Object> |
FALSE โ |
Set<Datetime> instanceOf Set<Object> |
FALSE โ |
Set<Decimal> instanceOf Set<Object> |
FALSE โ |
Set<Double> instanceOf Set<Object> |
FALSE โ |
Set<Id> instanceOf Set<Object> |
FALSE โ |
Set<Integer> instanceOf Set<Object> |
FALSE โ |
Set<Long> instanceOf Set<Object> |
FALSE โ |
Set<String> instanceOf Set<Object> |
FALSE โ |
Set<SObject> instanceOf Set<Object> |
FALSE โ |
- Other than
List
,Set<Object>
is NOT a supertype forSet<ConcreteType>
.
Set<Object>
– casting
- We CANNOT cast
Set<ConcreteType>
toSet<Object>
,
Set<Blob> mySetBlobs = new Set<Blob>{ Blob.valueof('StringToBlob') };
Set<Object> myBlobs = mySetBlobs;
// Illegal assignment from Set<Blob> to Set<Object>
Set<Boolean> mySetBooleans = new Set<Boolean>{ true };
Set<Object> myBooleans = mySetBooleans;
// Illegal assignment from Set<Boolean> to Set<Object>
Set<Date> mySetDates = new Set<Date>{ Date.today() };
Set<Object> myDates = mySetDates;
// Illegal assignment from Set<Date> to Set<Object>
Set<DateTime> mySetDateTimes = new Set<DateTime>{ DateTime.now() };
Set<Object> myDateTimes = mySetDateTimes;
// Illegal assignment from Set<DateTime> to Set<Object>
Set<Decimal> mySetDecimals = new Set<Decimal>{ 1.1 };
Set<Object> myDecimals = mySetDecimals;
// Illegal assignment from Set<Decimal> to Set<Object>
Set<Double> mySetDoubles = new Set<Double>{ 1261992 };
Set<Object> myDoubles = mySetDoubles;
// Illegal assignment from Set<Double> to Set<Object>
Set<Integer> mySetIntegers = new Set<Integer>{ 12345 };
Set<Object> myIntegers = mySetIntegers;
// Illegal assignment from Set<Integer> to Set<Object>
Set<Long> mySetLongs = new Set<Long>{ 4271990 };
Set<Object> myLongs = mySetLongs;
// Illegal assignment from Set<Long> to Set<Object>
Set<String> mySetStrings = new Set<String>{ 'myString' };
Set<Object> myStrings = mySetStrings;
// Illegal assignment from Set<String> to Set<Object>
Set<SObject> myAccounts = new Set<SObject>{ new Account() };
Set<Object> myAccountResults = myAccounts;
// Illegal assignment from Set<SObject> to Set<Object>
Even if you explicitly add casting (Set<Object>)
it will not work.
Set<Blob> mySetBlobs = new Set<Blob>{ Blob.valueof('StringToBlob') };
Set<Object> myBlobs = (Set<Object>) mySetBlobs;
// Incompatible types since an instance of Set<Blob> is never an instance of Set<Object>
Set<Boolean> mySetBooleans = new Set<Boolean>{ true };
Set<Object> myBooleans = (Set<Object>) mySetBooleans;
// Incompatible types since an instance of Set<Boolean> is never an instance of Set<Object>
Set<Date> mySetDates = new Set<Date>{ Date.today() };
Set<Object> myDates = (Set<Object>) mySetDates;
// Incompatible types since an instance of Set<Date> is never an instance of Set<Object>
Set<DateTime> mySetDateTimes = new Set<DateTime>{ DateTime.now() };
Set<Object> myDateTimes = (Set<Object>) mySetDateTimes;
// Incompatible types since an instance of Set<DateTime> is never an instance of Set<Object>
Set<Decimal> mySetDecimals = new Set<Decimal>{ 1.1 };
Set<Object> myDecimals = (Set<Object>) mySetDecimals;
// Incompatible types since an instance of Set<Decimal> is never an instance of Set<Object>
Set<Double> mySetDoubles = new Set<Double>{ 1261992 };
Set<Object> myDoubles = (Set<Object>) mySetDoubles;
// Incompatible types since an instance of Set<Double> is never an instance of Set<Object>
Set<Integer> mySetIntegers = new Set<Integer>{ 12345 };
Set<Object> myIntegers = (Set<Object>) mySetIntegers;
// Incompatible types since an instance of Set<Integer> is never an instance of Set<Object>
Set<Long> mySetLongs = new Set<Long>{ 4271990 };
Set<Object> myLongs = (Set<Object>) mySetLongs;
// Incompatible types since an instance of Set<Long> is never an instance of Set<Object>
Set<String> mySetStrings = new Set<String>{' myString' };
Set<Object> myStrings = (Set<Object>) mySetStrings;
// Incompatible types since an instance of Set<String> is never an instance of Set<Object>
Set<SObject> myAccounts = new Set<SObject>{ new Account() };
Set<Object> myAccountResults = (Set<Object>) myAccounts;
// Incompatible types since an instance of Set<SObject> is never an instance of Set<Object>
Set Summary
- Other than
List
,Set<Object>
is NOT a supertype forSet<ConcreteType>
.
Map
Map<SObject>
Map<SObject>
– instanceOf
I skipped cases where SObject
is a key. SObject
should never be a key in the Map.
Assert.isTrue(new Map<Object, Account>() instanceof Map<Object, Object>);
// Operation instanceof is always true since an instance of Map<Object,Account> is always an instance of Map<Object,Object>
Assert.isTrue(new Map<Object, Account>() instanceof Map<Object, SObject>);
// Operation instanceof is always true since an instance of Map<Object,Account> is always an instance of Map<Object,SObject>
Key Type | Value Type | Key Type | Value Type | Is instanceOf |
---|---|---|---|---|
Object | Account | Object | Object | TRUE โ |
Object | Account | Object | SObject | TRUE โ |
Map<Object, Account>
is an instance ofMap<Object, Object>
, which means thatMap<Object, Object>
is a supertype ofMap<Object, Account>
.Map<Object, Account>
is an instance ofMap<Object, SObject>
, which means thatMap<Object, SObject>
is a supertype ofMap<Object, Account>
.
Map<SObject>
– casting
Upcasting
Why it works?
Map<Object, Object>
is a supertype forMap<Object, Standard/CustomObject>
.- Conversion from
Map<Object, Standard/CustomObject>
toMap<Object, Object>
is called Upcasting. - As you already know from Upcasting section. Upcasting can be done explicitly or implicitly.
โ
Map<Object, Object> myMap = new Map<Object, Account>();
Map<Id, Object> myMap2 = new Map<Id, Account>();
Map<Object, SObject> myMap = new Map<Object, Account>();
Map<Id, SObject> myMap2 = new Map<Id, Account>();
Downcasting
โ
Map<Object, Object> myMap = new Map<Object, Account>();
// Illegal assignment from Map<Object,Object> to Map<Object,Account>
Map<Object, Account> myMap = new Map<Object, SObject>();
// Illegal assignment from Map<Object,SObject> to Map<Object,Account>
Even explicit casting will not work. The error is different.
Map<Object, Account> myMap = (Map<Object, Account>) new Map<Object, Object>();
//System.TypeException: Invalid conversion from runtime type Map<ANY,ANY> to Map<ANY,Account>
Map<Object, Account> myMap = (Map<Object, Account>) new Map<Object, SObject>();
// System.TypeException: Invalid conversion from runtime type Map<ANY,SObject> to Map<ANY,Account>
How to fix Map downasting?
โ
SObjectType ofObject = Account.SObjectType;
Map<Id, SObject> idToSObject = (Map<Id, SObject>) Type.forName('Map<Id, ' + ofObject + ' >').newInstance();
Map<Id, Account> idToAccount = (Map<Id, Account>) idToSObject;
String ofObject = 'Account'
Map<Id, SObject> idToSObject = (Map<Id, SObject>) Type.forName('Map<Id, ' + ofObject + ' >').newInstance();
Map<Id, Account> idToAccount = (Map<Id, Account>) idToSObject;
Map<Object>
Map<Object>
– instanceOf
Assert.isTrue(new Map<String, String>() instanceOf Map<Object, Object>);
// Operation instanceOf is always false since an instance of Map<String,String> is never an instance of Map<Object,Object>
Assert.isTrue(new Map<String, String>() instanceOf Map<String, Object>);
// Operation instanceOf is always true since an instance of Map<String,String> is always an instance of Map<String,Object>
Assert.isTrue(new Map<String, String>() instanceOf Map<Object, String>);
// Operation instanceOf is always false since an instance of Map<String,String> is never an instance of Map<Object,String>
Assert.isTrue(new Map<String, Object>() instanceOf Map<Object, Object>);
// Operation instanceOf is always false since an instance of Map<String,Object> is never an instance of Map<Object,Object>
Assert.isTrue(new Map<String, Object>() instanceOf Map<Object, String>);
// Operation instanceOf is always false since an instance of Map<String,Object> is never an instance of Map<Object,String>
Assert.isTrue(new Map<String, Object>() instanceOf Map<String, String>);
// FALSE
Assert.isTrue(new Map<Object, String>() instanceOf Map<Object, Object>);
// Operation instanceOf is always true since an instance of Map<Object,String> is always an instance of Map<Object,Object>
Assert.isTrue(new Map<Object, String>() instanceOf Map<String, Object>);
// Operation instanceOf is always false since an instance of Map<Object,String> is never an instance of Map<String,Object>
Assert.isTrue(new Map<Object, String>() instanceOf Map<String, String>);
// Operation instanceOf is always false since an instance of Map<Object,String> is never an instance of Map<String,String>
Key Type | Value Type | Key Type | Value Type | Is Instance Of |
---|---|---|---|---|
String | String | Object | Object | FALSE โ |
String | String | String | Object | TRUE โ |
String | String | Object | String | FALSE โ |
String | Object | Object | Object | FALSE โ |
String | Object | Object | String | FALSE โ |
String | Object | String | String | FALSE โ |
Object | String | Object | Object | TRUE โ |
Object | String | String | Object | FALSE โ |
Object | String | String | String | FALSE โ |
Maps are the same instance only in the following cases:
new Map<MyType, MyType>() instanceOf new Map<MyType, Object>
new Map<Object, MyType>() instanceOf new Map<Object, Object>
Key Type must be the same.
Map<Object>
– casting
โ
Map<Object, Object> objectObjectStringString = new Map<String, String>();
// Illegal assignment from Map<String,String> to Map<Object,Object>
Map<Object, String> objectStringStringString = new Map<String, String>();
// Illegal assignment from Map<String,String> to Map<Object,String>
Map<Object, Object> objectObjectStringObject = new Map<String, Object>();
// Illegal assignment from Map<String,Object> to Map<Object,Object>
Map<Object, String> objectStringStringObject = new Map<String, Object>();
// Illegal assignment from Map<String,Object> to Map<Object,String>
Map<String, String> stringStringStringObject = new Map<String, Object>();
// Illegal assignment from Map<String,Object> to Map<String,String>
Map<String, Object> stringObjectObjectString = new Map<Object, String>();
// Illegal assignment from Map<Object,String> to Map<String,Object>
Map<String, String> StringStringObjectString = new Map<Object, String>();
// Illegal assignment from Map<Object,String> to Map<String,String>
โ
Map<String, Object> stringObjectStringString = new Map<String, String>();
Map<Object, Object> objectObjectObjectString = new Map<Object, String>();
You can cast implicitly only when:
new Map<MyType, MyType>() instanceOf new Map<MyType, Object>
new Map<Object, MyType>() instanceOf new Map<Object, Object>
Map Summary
Iterable
Starting from Summer 23′, Set
implements Iterable
interface as List
does.
Iterable List
Iterable List – instanceOf
Assert.isTrue(new List<Object>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of List<Object> is always an instance of System.Iterable<Object>
Assert.isTrue(new List<Blob>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Boolean>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Date>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Datetime>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Decimal>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Double>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Id>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Integer>() instanceOf Iterable<Object>);
Assert.isTrue(new List<Long>() instanceOf Iterable<Object>);
Assert.isTrue(new List<String>() instanceOf Iterable<Object>);
Assert.isTrue(new List<SObject>() instanceOf Iterable<Object>);
Not surprisingly, a List
of concrete types is also an instance of Iterable<Object>
.
Expression | is instanceOf Iterable<Object> |
---|---|
List<Blob> instanceOf Iterable<Object> |
TRUE โ |
List<Boolean> instanceOf Iterable<Object> |
TRUE โ |
List<Date> instanceOf Iterable<Object> |
TRUE โ |
List<Datetime> instanceOf Iterable<Object> |
TRUE โ |
List<Decimal> instanceOf Iterable<Object> |
TRUE โ |
List<Double> instanceOf Iterable<Object> |
TRUE โ |
List<Id> instanceOf Iterable<Object> |
TRUE โ |
List<Integer> instanceOf Iterable<Object> |
TRUE โ |
List<Long> instanceOf Iterable<Object> |
TRUE โ |
List<String> instanceOf Iterable<Object> |
TRUE โ |
List<SObject> instanceOf Iterable<Object> |
TRUE โ |
Assert.isTrue(new List<Object>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of List<Object> is always an instance of System.Iterable<Object>
Assert.isFalse(new Set<Object>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Object> is always an instance of System.Iterable<Object>
- Instance of
List<Object>
andSet<Object>
are always an instance ofSystem.Iterable<Object>
.
Iterable List – casting
โ
Iterable<Object> myIterableObjects = new List<Object>();
โ
Iterable<Object> myIterableBlobs = new List<Blob>();
// Illegal assignment from List<Blob> to System.Iterable<Object>
Iterable<Object> myIterableBooleans = new List<Boolean>();
// Illegal assignment from List<Boolean> to System.Iterable<Object>
Iterable<Object> myIterableDates = new List<Date>();
// Illegal assignment from List<Date> to System.Iterable<Object>
Iterable<Object> myIterableDatetimes = new List<Datetime>();
// Illegal assignment from List<Datetime> to System.Iterable<Object>
Iterable<Object> myIterableDecimals = new List<Decimal>();
// Illegal assignment from List<Decimal> to System.Iterable<Object>
Iterable<Object> myIterableDoubles = new List<Double>();
// Illegal assignment from List<Double> to System.Iterable<Object>
Iterable<Object> myIterableIds = new List<Id>();
// Illegal assignment from List<Id> to System.Iterable<Object>
Iterable<Object> myIterableIntegers = new List<Integer>();
// Illegal assignment from List<Integer> to System.Iterable<Object>
Iterable<Object> myIterableLongs = new List<Long>();
// Illegal assignment from List<Long> to System.Iterable<Object>
Iterable<Object> myIterableStrings = new List<String>();
// Illegal assignment from List<String> to System.Iterable<Object>
Iterable<Object> myIterableSObjects = new List<SObject>();
// Illegal assignment from List<SObject> to System.Iterable<Object>
It’s really interesting.
e.g List<String>
is an instance of Iterable<Object>
, but you CANNOT use Iterable<Object>
as a supertype.
โ
Iterable<Object> myIterableStrings = new List<String>();
โ
You need to assign List<String>
to List<Object>
and after it to Iterable<Object>
.
List<Object> myStrings = new List<String>();
Iterable<Object> myIterableObjects = myStrings;
Iterable Set
Iterable Set – instanceOf
Assert.isTrue(new Set<Blob>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Blob> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Boolean>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Boolean> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Date>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Date> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Datetime>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Datetime> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Decimal>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Decimal> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Double>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Double> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Id>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Id> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Integer>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Integer> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<Long>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<Long> is always an instance of System.Iterable<Object>
Assert.isTrue(new Set<String>() instanceOf Iterable<Object>);
// Operation instanceOf is always true since an instance of Set<String> is always an instance of System.Iterable<Object>
Assert.isFalse(new Set<SObject>() instanceOf Iterable<Object>);
Expression | is instanceOf |
---|---|
Set<Blob> instanceOf Iterable<Object> |
TRUE โ |
Set<Boolean> instanceOf Iterable<Object> |
TRUE โ |
Set<Date> instanceOf Iterable<Object> |
TRUE โ |
Set<Datetime> instanceOf Iterable<Object> |
TRUE โ |
Set<Decimal> instanceOf Iterable<Object> |
TRUE โ |
Set<Double> instanceOf Iterable<Object> |
TRUE โ |
Set<Id> instanceOf Iterable<Object> |
TRUE โ |
Set<Integer> instanceOf Iterable<Object> |
TRUE โ |
Set<Long> instanceOf Iterable<Object> |
TRUE โ |
Set<String> instanceOf Iterable<Object> |
TRUE โ |
Set<SObject> instanceOf Iterable<Object> |
FALSE โ |
- An interesting thing is that you’re getting an error
Operation instanceOf is always true...
. Set<ConcreteType>
is also an instance ofIterable<Object>
, but notSet<SObject>
.
Iterable Set – casting
โ
Iterable<Object> myIterableObjects = new Set<Object>();
โ
Iterable<Object> myIterableBlobs = new Set<Blob>();
Iterable<Object> myIterableBooleans = new Set<Boolean>();
Iterable<Object> myIterableDates = new Set<Date>();
Iterable<Object> myIterableDatetimes = new Set<Datetime>();
Iterable<Object> myIterableDecimals = new Set<Decimal>();
Iterable<Object> myIterableDoubles = new Set<Double>();
Iterable<Object> myIterableIds = new Set<Id>();
Iterable<Object> myIterableIntegers = new Set<Integer>();
Iterable<Object> myIterableLongs = new Set<Long>();
Iterable<Object> myIterableStrings = new Set<String>();
Iterable<Object> myIterableSObjects = new Set<SObject>();
// Illegal assignment from Set<SObject> to System.Iterable<Object>
- You CAN use
Iterable<Object>
as a supertype forSet
, which you CANNOT do with aList
. - You CANNOT assign
Set<SObject>
toIterable<Object>
.
Summary
It’s quite a big deal. Let’s check an example:
public interface Filter {
Filter isIn(Iterable<Object> inList);
}
public class MyFilter implements Filter {
public Filter isIn(Iterable<Object> inList) {
return this;
}
}
โ
MyFilter myFilter = new MyFilter();
myFilter.isIn(new List<String>{ 'Test1', 'Test2' });
// Method does not exist or incorrect signature: void isIn(List<String>) from the type Filter
myFilter.isIn(new List<Decimal>{ 1, 2 });
// Method does not exist or incorrect signature: void isIn(List<Decimal>) from the type Filter
โ
MyFilter myFilter = new MyFilter();
myFilter.isIn(new List<Object>{ 1, 2, 'Test1', 'Test2' });
myFilter.isIn(new Set<String>{ 'Test1', 'Test2 '});
myFilter.isIn(new Set<Decimal>{ 1, 2 });
myFilter.isIn(new Set<Object>{ 1, 2, 'Test1', 'Test2 ' });
How to fix it?
๐จ
- You need two methods (
isIn(Iterable<Object> inList)
andisIn(List<Object> inList)
) in the interface that will be covered by one method (isIn(Iterable<Object> inList)
in concrete class!
public interface Filter {
Filter isIn(Iterable<Object> inList);
Filter isIn(List<Object> inList);
}
public class MyFilter implements Filter {
public Filter isIn(Iterable<Object> inList) {
return this;
}
}
Iterable Summary
- List
- Instance of
List<Object>
andSet<Object>
are always an instance ofSystem.Iterable<Object>
. - You CANNOT use
Iterable<Object>
as a supertype forList<ConcreteType>
. You need to assignList<ConcreteType>
toList<Object>
and after it toIterable<Object>
.
- Instance of
- Set
Set<ConcreteType>
is instance ofIterable<Object>
.Set<Sobject>
is NOT instance ofSet<SObject>
.
Casting Rules
Cast to everything
The problem with the solution below is performance.
โ
Map<Object, SObject> someKeyToRecord = new Map<Object, SObject>{
'My Account' => new Account(Name = 'My Account')
};
Map<String, Account> nameToAccount = (Map<String, Account>) JSON.deserialize(JSON.serialize(someKeyToRecord), Map<String, Account>.class);
Casting Cheat Sheet
Do Not Trust instanceOf
Based on the type system is broken with regards to collections:
Pretty much the entire "Type" system that governs Maps, Sets, and Lists is broken. Do not trust instanceOf, use your own logical assessment to determine if something is safe or not.
As shown in the post, there are cases where instanceOf
does not work correctly.
e.g
List<SObject>
and List<Object>
instanceOf
says that "List<SObject>
is never an instance of List<Object>
", but you can assign List<SObject>
to List<Object>
.
โ
Assert.isFalse(new List<SObject>() instanceOf List<Object>);
// Operation instanceOf is always false since an instance of List<SObject> is never an instance of List<Object>
โ
List<Object> sObjects = new List<SObject>();
List<ConcreteType>
and Iterable<Object>
instanceOf
says that List<ConcreteType>
is an instance of Iterable<Object>
, but you CANOT assign List<ConcreteType>
to Iterable<Object>
.
โ
Iterable<Object> myIterableStrings = new List<String>();
โ
You need to assign List<String>
to List<Object>
and after it to Iterable<Object>
.
List<Object> myStrings = new List<String>();
Iterable<Object> myIterableObjects = myStrings;
SObject Casting
SObject
is a supertype for:- all standard objects (Account, Contact, etc.)
- all custom objects (MyCustomObject__c)
SObject account = new Account(Name = 'My Account');
SObject myObject = new MyCustomObject__c();
- Casting from
Standard/Custom Object
toSObject
is called upcasting and can be implicitly.
SObject account = new Account(Name = 'My Account');
- Casting from
SObject
toStandard/Custom Object
is called downcasting and it needs to be explicit.
SObject account = new Account(Name = 'My Account');
Account myAccount = (Account) account;
SObject
is instance ofObject
.Object
is a supertype forSObject
.
Object account = new Account(Name = 'My Account');
- Casting from
SObject
toObject
is called upcasting and can be implicit.
Object account = new Account(Name = 'My Account');
- Casting from
Object
toSObject
is called downcasting and it needs to be explicit.
Object account = new Account(Name = 'My Account');
SObject myAccount = (SObject) account;
Object Casting
Object
is a supertype for:- all standard objects
- all custom objects
- all apex classes
- all collections (List, Set and Map)
- all apex types (Integer, String, Boolean)
Primitive Types Casting
- All Primitive Data Types are
instanceOf
Object
.Object
is a supertype for all primitve types. - Casting from Primitive Data Types to
Object
is called upcasting and can be implicit.
String myString = 'myString';
Object myStringResult = myString;
List Casting
- All
List<ConcreteType>
are instance ofList<Object>
.List<Object>
is a supertype ofList<ConcreteType>
. - Based on
instanceOf
methodList<SObject>
is NOT an instance ofList<Object>
, but still you can assignList<SObject>
toList<Object>
. Do not trustinstanceOf
. - Casting from
List<ConcreteType>
toList<Object>
is called upcasting and can be implicit.
List<String> myStrings = new List<String>{ 'myString' };
List<Object> myStringResult = myStrings;
List<SObject> myAccounts = new List<SObject>{ new Account() };
List<Object> myAccountResults = myAccounts;
List<SObject>
is a supertype forList<Standard/Custom>
.
List<Account> accounts = new List<Account>();
List<SObject> myAccounts = accounts;
๐จ
List<Standard/Custom>
is a supertype forList<SObject>
.
List<SObject> accounts = new List<Account>();
List<Account> myAccounts = accounts;
List<SObject> accounts = new List<SObject>();
List<Account> myAccounts = accounts;
Set Casting
- Other than
List
,Set<Object>
is NOT a supertype forSet<ConcreteType>
. - You CANNOT cast
Set<ConcreteType>
toSet<Object>
.
Set<String> mySetStrings = new Set<String>{' myString' };
Set<Object> myStrings = (Set<Object>) mySetStrings;
// Incompatible types since an instance of Set<String> is never an instance of Set<Object>
Map Casting
Map<Object, Account>
is instance ofMap<Object, Object>
, it means thatMap<Object, Object>
is a supertype forMap<Object, Account>
.Map<Object, Account>
is instance ofMap<Object, SObject>
, it means thatMap<Object, SObject>
is a supertype forMap<Object, Account>
.
Map<Object, Object> myMap = new Map<Object, Account>();
Map<Id, Object> myMap2 = new Map<Id, Account>();
Map<Object, SObject> myMap = new Map<Object, Account>();
Map<Id, SObject> myMap2 = new Map<Id, Account>();
- To fix
System.TypeException: Invalid conversion from runtime type Map<ANY,SObject> to Map<ANY,Account>
dynamic Map initiation is needed.
SObjectType ofObject = Account.SObjectType;
Map<Id, SObject> idToSObject = (Map<Id, SObject>) Type.forName('Map<Id, ' + ofObject + ' >').newInstance();
Map<Id, Account> idToAccount = (Map<Id, Account>) idToSObject;
Iterable Casting
- List
- Instance of
List<Object>
andSet<Object>
are always an instance ofSystem.Iterable<Object>
. - You CANNOT use
Iterable<Object>
as a supertype forList<ConcreteType>
. You need to assignList<ConcreteType>
toList<Object>
and after it toIterable<Object>
.
- Instance of
List<Object> myStrings = new List<String>();
Iterable<Object> myIterableObjects = myStrings;
- Set
Set<ConcreteType>
is instance ofIterable<Object>
, butSet<SObject>
is NOT instance ofIterable<SObject>
.
Iterable<Object> myIterableObjects = new Set<Object>();