18

Apex provides at least two different methods for polymorphism (that is, writing code that can use objects of different classes in a uniform way):

  1. Standard inheritance-based polymorphism, where code is written to use one class (the base class) but objects of a derived class (defined using the "extends" keyword) may be supplied instead
  2. Interface-based polymorphism, where an empty interface class is defined that other classes may implement. Those classes may then be used wherever the interface class is expected.

Can anyone supply a practical example of either in use in a Salesforce context, and how they might differ?

1 Answer 1

26

As I have gotten familiar with others implementations and best practices over time I tend to use both in different situations.

Interfaces:
Interfaces are absolutely fantastic for generalized API's that are re-used in many different contexts. For example: Apex-Lang's ArrayUtils.qsort I have made it a requirement in the past that all sorting outside of SOQL should be implemented using this interface. Why? because of the interface you can sort any object by its properties in a completely predictable manner, every time. No multiple dictionary mutation funny business. It cleanly provides a very clear re-usable approach to sorting objects, much like the Comparator interface in Java.

What are interfaces not good at? I have never had good luck implementing an interface as a controller for a visualforce page. Why? Because visualforce requires getter/setter methods in order to access properties and the idea of having to define each and every getter setter and then implement it defeats the purpose of re-usability.

This brings us to abstract/virtual classes.

Abstract/Virtual Classes:
In Apex abstract classes are great for creating re-usable patterns for implementing controllers (among other things). If you ever implement a visualforce page in a site you'll find that if there is any uncaught runtime error the user will only see a stanard permission exception page (hell to debug). Instead of try catching every single contructor or initalize/action method you can write an abstract class that implements the various constructors and then use a one line method in the child class: (psuedo code)

 public abstract class B{
     sObject sobj;
     public B(){}
     public B(ApexPages.StandardController r){
         try{
            this.sobj = r.getRecord();
            //do something standard
         }
         catch(Exception e){
           ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
         }
     }
 }
 class A extends B{
     public A(ApexPages.StandardController r){
          super(r);
     }
 }

You must log in to answer this question.

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