5

I'm not sure how to solve the following:

public String dummy(SObject[] obj) {
   obj.getsomething();
}

obj can be two different objects (both of them implement a method name getsomething).

The name of the objects are only known on runtime.

I've tried the following:

public String dummy(SObject[] obj) {
   ((getObjectName())obj).getsomething();
}

But It's not possible in apex.

Any suggestions?

EDIT:

Actually it is SObject - As I switched the KnowledgeArticle to lightning the SObject can be (KnowledgeArticleVersion or Knowledge_Kav).

3 Answers 3

3

Adding a separate answer for SObject, as it is a very different question and therefore the answer is quite different. To reiterate:

Please note that SObject and Object are very different types. And adding [] at the end of your type definition makes it a List, again a huge difference.

Anyway, if your method accepts List<SObject> and you want dynamic logic based on that, you should read up on Dynamic Apex. A couple methods will be useful for you here:

  • List<SObject>.getSObjectType()
  • SObject.get(String field)

You may want a map of SObjectType to field. One way that might work:

static Map<SObjectType, SObjectField> fieldsToCheck = new Map<SObjectType, SObjectField>
{
    MyObject__c.sObjectType => MyObject__c.SomeField__c,
    OtherObject__c.sObjectType => OtherObject__c.OtherField__c
};

public static void doStuff(List<SObject> records)
{
    if (record == null) { /* figure out if/how to handle null inputs */ }

    SObjectField field = fieldsToCheck.get(records.getSObjectType());
    if (field == null) { /* figure out how to handle unsupported input */ }

    for (SObject record : records)
    {
        Object value = record.get(field);
        // do stuff with value
    }
}

A couple notes on nomenclature:

  • An object is a type definition. It can be either a primitive or a standard/custom class.
  • An SObject is a table in your database.
  • An instance is a construction of either of the above.
  • A record is an instance of an SObject.

Try to keep these in mind when naming your variables.

8

Please note that SObject and Object are very different types. And adding [] at the end of your type definition makes it a List, again a huge difference.

The text of your post indicates you meant Object, so I will answer as if that's the case.

Regardless, the key here is that if you have a few different types you want to guarantee all implement a specific method, use an interface.

interface Foo
{
    void getSomething();
}

Then, assuming you know your Object collection passed in contains implementations of this interface, you would call:

for (Object instance : collection)
{
    Foo implementation = (Foo)instance;
    implementation.getSomething();
}

Make sure to add the implements keyword to your other classes:

public class Bar implements Foo
{
    public void getSomething() { /*implementation*/ }
}

You can read much more about how interfaces work in the documentation.

2
  • Thanks for the answer. Actually it is SObject - As I switched the KnoledgeArticle to lightning the SObject can be (KnowledgeArticleVersion or Knowledge_Kav) Apr 9, 2018 at 15:33
  • Yeah @omri I added a separate answer that addresses the other interpretation of your question.
    – Adrian Larson
    Apr 9, 2018 at 15:41
4

Apex doesn't really have much in the way of reflection or introspection.

While we do have the Type class (which has the forName() method), you still need to know the name of the object at compile time to be able to really make use of it.

forName() takes a string, and you can call newInstance() to get an instance of the type that was returned by forName(), but newInstance() returns a generic object...which you won't be able to call any methods on without downcasting to a more specialized type (which is the thing we're trying to avoid knowing at compile-time in the first place).

Instead of trying to cast to a specific class, this sounds like a situation where you should make use of an interface instead.

The idea is that the interface tells you which methods are available, what their return type is, and the parameters that need to be passed to each method.

public interface IMyInterface{
    Integer doSomeMath(Integer arg1, Integer arg2);
}

Other classes can then implement that interface

// 'implements <interface name>' is the syntax here that you add to the class
//   definition
public class MyClass implements IMyInterface{

    // Implementing an interface means that you need to "implement" all of
    //   the methods specified by that interface
    public Integer doSomeMath(Integer arg1, Integer arg2){
        return arg1 + arg2;
    }
}

public class MyOtherClass implements IMyInterface{

    // Other classes can have other implementations.
    // The point is that the method signature is the same
    public Integer doSomeMath(Integer arg1, Integer arg2){
        return arg1 * arg2;
    }
}

Part of the power of interfaces is that you can treat any class that implements an interface as if it were an instance of that type.

List<IMyInterface> interfaceList = new List<IMyInterface>();
// We can typecast both classes as IMyInterface
// More importantly, we can know about this interface type at compile-time
interfaceList.add((IMyInterface)new MyClass());
interfaceList.add((IMyInterface)new MyOtherClass());

// Now that they're the same "type", we can call the interface methods on them
//   without further casting.
for(IMyInterface implementation :interfaceList){
    system.debug(implementation.doSomeMath(2, 3));
}
1
  • Thanks for the answer. Actually it is SObject - As I switched the KnoledgeArticle to lightning the SObject can be (KnowledgeArticleVersion or Knowledge_Kav) Apr 9, 2018 at 15:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .