I have read this SO post, but I am asking a slightly different question:
I would like to be able to write a method that can accept a Set
with any parameterized type.
e.g. myMethod(Set<Object> genericSet)
If I were wanting to do the same thing with a List
, then I could using List<Object>
because the following is possible:
List<Object> genericList = new List<String>();
In other words List<Object>
can act as an abstraction of List<String>
.
However, I can't use Set<Object>
as a method parameter and expect to be able to pass in Set<String>
because the following throws a compilation error:
Set<Object> genericSet = new Set<String>();
I'm not sure why this is. Possibly something to do with the fact that different types have different hashCode()
functions?
Alternative
As an alternative, I could just have my parameter be of type Object
, which would allow me to pass in any type of Set<?>
. However, the problem with this is that I need to check that the argument passed in is indeed a Set of some sort. Furthermore, if it is, then because generic sets aren't allowed, I would need to know the exact type so that I can cast it to the correct set type.
I can't use myArg instanceof Set
because Set has to has some sort of parameterized type.
And because of the issue I outlined above, I can't use myArg instanceof Set<Object>
because this will return false for everything except when the parameterized type really is Object
.
Does anyone know how I might be able to get some sort of generic behaviour for Sets?
Best Answer
The type system is oddly broken in a number of ways that they're also broken in Java, in addition to a unique set of problems in Apex that Phil W linked to.
However, if you're interested in a solution, you can indeed use sets and lists interchangeably through the use of Iterable. Unfortunately, it will require a cast every time you want to use it. Here's an Execute Anonymous script you can check out.
Notice how we can extract values from a list or set of any time if we cast it to Iterable first. Unfortunately, we still can't get to a "concrete" type dynamically, but you can use this on a case-by-case basis to work within the limitations of Apex.