Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

How to make a call to interface method from the class which implements this interface

public interface IA {
void m1();
}
public abstract class A implements IA {
void m2() {/*how to make a call to m1 here*/ }
}
public class AClass extends A {
void m1();
}

For example what is wrong in execute method so that I can't call methods identified in interface.

public class TriggerManager {
    public interface ITriggerHandler {//TriggerManager.ITriggerHandler
        void onBeforeInsert(List<sObject> newRecords);

        void onBeforeUpdate(List<SObject> oldRecords, List<SObject> newRecords, Map<ID, SObject> oldRecordsMap, Map<ID, SObject> newRecordsMap);

        void onBeforeDelete(List<sObject> oldRecords, Map<ID, sObject> oldRecordsMap);

        void onAfterInsert(List<sObject> newRecords, Map<ID, sObject> newRecordsMap);

        void onAfterUpdate(List<sObject> oldRecords, List<sObject> newRecords, Map<ID, sObject> oldRecordsMap, Map<ID, sObject> newRecordsMap);

        void onAfterDelete(List<sObject> oldRecords, Map<ID, sObject> oldRecordsMap);
    }             

    public abstract class TriggerHandler implements ITriggerHandler {
        private void execute(Boolean isBefore, Boolean isAfter, Boolean isInsert, Boolean isUpdate, Boolean isDelete, 
            List<SObject> oldRecords, List<SObject> newRecords, Map<ID, SObject> oldRecordsMap, Map<ID, SObject> newRecordsMap) {
            /*
            if(isBefore) {
                if (isInsert) onBeforeInsert(newRecords);
                else if (isUpdate) onBeforeUpdate(oldRecords, newRecords, oldRecordsMap, newRecordsMap);
                else if (isDelete) onBeforeDelete(oldRecords, oldRecordsMap);
            }
            else {
                if (isInsert) onAfterInsert(newRecords, newRecordsMap);
                else if (isUpdate) onAfterUpdate(oldRecords, newRecords, oldRecordsMap, newRecordsMap);
                else if (isDelete) onAfterDelete(oldRecords, oldRecordsMap);
            } 
            */                               
        }
    }

    public static void handle(TriggerHandler handler) {
        handler.execute(
                Trigger.isBefore, 
                Trigger.isAfter, 
                Trigger.isInsert, 
                Trigger.isUpdate, 
                Trigger.isDelete,
                Trigger.old, 
                Trigger.new, 
                Trigger.oldMap,
                Trigger.newMap);
    }
}

What other items did I miss in this architecture?

share|improve this question
    
Are you getting an error that the methods don't exist in the interface when trying to call the from the abstract class? As a guess I'd declare the unimplemented interface methods as abstract in the abstract class. –  Daniel Ballinger Mar 3 at 22:38
    
Compile Error: Method does not exist or incorrect signature: [TriggerManager.TriggerHandler].onBeforeInsert(LIST<SObject>) –  Natallia Mar 3 at 22:44

2 Answers 2

up vote 2 down vote accepted

In your abstract classes you will need to impliment the interface explicitly, even if you just make the required methods abstract.

E.g.

public interface IA {
    void m1();
}
public abstract class A implements IA {
    void m2() {
        // Call the method defined in the interface.
        m1();
    }
    // Explicitly declare the interface method that the subclass must implement
    abstract void m1();
}
public class AClass extends A {
    void m1();
}
share|improve this answer

Just as a Class has variables, interfaces have methods. A class can implement an interface if the class has all of the interface's methods. So, how is this useful? Here's an example:

Given an interface,

public interface anAwesomeInterface{
    void customSave();
}

and classes class1, class2, and class3 implementing anAwesomeInterface.

public class class1 implements anAwesomeInterface{
    public void customSave(){
        // however you save an instance of class1
    }
}

public class class2 implements anAwesomeInterface{
    public void customSave(){
        // however you save an instance of class2
    }
}

public class class3 implements anAwesomeInterface{
    public void customSave(){
        // however you save an instance of class3
    }
}    

Now let's make some collections. We can do the following:

class1 anExampleOf_class1 = new class1();
class2 anExampleOf_class2 = new class2();
class2 anotherExampleOf_class2 = new class2();
class3 anExampleOf_class3 = new class3();

anAwesomeInterface aai_exampleOfClass1 = new class1();
anAwesomeInterface aai_anotherExmapleOf_class2 = anotherExampleOf_class2;

list<anAwesomeInterface> anAwesomeList = new list<anAwesomeInterface>();
anAwesomeList.add(anExampleOf_class1);
anAwesomeList.add(anExampleOf_class2);
anAwesomeList.add(anotherExampleOf_class2);
anAwesomeList.add(anExampleOf_class3);
anAwesomeList.add(aai_exampleOfClass1);
anAwesomeList.add(aai_anotherExmapleOf_class2);

for(anAwesomeInterface a:anAwesomeList)
    a.customSave();  // each gets saved depending on its class's customSave method

Another example would be how Account implements sObject. An Account instance can both be an Account and an sObject depending how you want to use it.


Interfaces define common action among classes -- or maybe it's better the other way around, classes that have common actions define an interface.

So, the idea of interfaces is knowing what actions you want to do without specifically defining the class that's using the action.

This comes in handy when you want every class to have a specific action, though each class does that action in its own way.

A good example of this is implementing a Sharing Model for a Salesforce Org. Typically, every object's Oraginization-Wide Default will be set to Private, and we'll need a trigger on every object to manage it's sharing. Due to the nature of the problem, we'll have to perform an different action for each DML type -- insert, update, and delete -- for each Object! So, to streamline this, create an interface and a static method in a class called Sharing.

public class Sharing{

    public interface sharingInterface{
        void shareOnInsert(list<sObject> newList);
        void shareOnUpdate(list<sObject> newList,map<id,sObject> oldMap);
        void shareOnDelete(map<id,sObject> oldMap);
    }

    public static void sharingTrigger(string sObjectName,list<sObject> newList, map<id,sObject> oldMap,boolean isInsert,boolean isUpdate,boolean isDelete){
    sObjectType objectType=Schema.getGlobalDescribe().get(sObjectName);
        if(objectType==null){
            // invalid sObjectName
            system.debug(system.LoggingLevel.ERROR,'.... ERROR in Sharing.sharingTrigger('+sObjectName+',*,*,'+isInsert+','+isUpdate+','+isDelete+').  INVALID_SOBJECT_NAME: '+sObjectName);
            system.assertNotEquals(null,objectType,'.... ERROR in Sharing.sharingTrigger('+sObjectName+',*,*,'+isInsert+','+isUpdate+','+isDelete+').  INVALID_SOBJECT_NAME: '+sObjectName);
        }
        sharingInterface sharingInterfaceHelper;
        try{
            sharingInterfaceHelper=(sharingInterface )type.forName(sObjectName.replace('__c','_sharingHelper'));
        } catch(exception e){
            system.debug(system.LoggingLevel.ERROR,'.... ERROR in Sharing.sharingTrigger('+sObjectName+',*,*,'+isInsert+','+isUpdate+','+isDelete+').  ERROR: '+e);
            return;
        }
        if(isInsert)
            sharingInterfaceHelper.shareOnInsert(newList);
        if(isUpdate)
            sharingInterfaceHelper.shareOnUpdate(newList,oldMap);
        if(isDelete)
            sharingInterfaceHelper.shareOnDelete(oldMap);
    }//END sharingTrigger(list<sObject> newList,map<id,sObject> oldMap,trigger.isInsert,trigger.isUpdate,trigger.isDelete)

}

So, to use this interface, we need to do two things: (1) implement the interface in an actual Class, and (2) use the method in the appropriate trigger. Note that the method sharingTrigger requires the naming convention of our classes be the same name as the sObject but with the __c replaced with _sharingHelper.

What's cool about the method is that we take the string input sObjectName and use it to create an instance of the class we want that implements sharingInterface via type.forName(). Then, since it's an instance of sharingInterface, we can only use shairngInterface methods, namely those defined in the interface. (The interface is those methods -- it's what's the same among all classes that implement that interface)

(1) to share the sObject Employee__c in Sharing

public class Employee_sharingHelper{

    public void sharOnInsert(list<sObject> newList){
        list<Employee__c> employeeNewList = (list<Employee__c>)newList; // setting trigger context variable to a more useable list
        // do whatcha gotta to share Employee__c's on Insert 
    }
    public void sharOnUpdate(list<sObject> newList,map<id,sObject> oldMap){
        list<Employee__c> employeeNewList = (list<Employee__c>)newList; // setting trigger context variable to a more useable list
        map<id,Employee__c> employeeOldMap=(map<id,Employee__c>)oldMap;
        // do whatcha gotta to share Employee__c's on Update.  Maybe compare lookup fields, etc.
    }
    public void sharOnDelete(map<id,sObject> oldMap){
        map<id,Employee__c> employeeOldMap=(map<id,Employee__c>)oldMap;
        // do whatcha gotta to share Employee__c's on Delete
    }
}

Then, to use this, we simply need to add the method sharingTrigger on an Employee__c trigger.

public triger on Employee__c(after insert,after update,after delete){
    Sharing.sharingTrigger('Employee__c',trigger.new,trigger.oldMap,trigger.isInsert,trigger.isUpdate,trigger.isDelete);

Why was all of this worth it? Well, (1) every single one of our triggers became one-liners. (2) All logic is stream-lined, so hopefully it's easier to understand and easier to fully-test, and (3) if we had to manage sharing for another object, all we'd have to do is create another class that implements sharingInterface and then write the one-line trigger. And note that to implement sharingInterface, you have to have the methods shareOnInsert, shareOnUpdate, shareOnDelete, so the developer is forced to write those methods / worry about those scenarios. It's like a Validation Rule to enforce good/smart coding.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.