[SalesForce] What are the best practices for using polymorphism in Apex

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?

Best Answer

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);
     }
 }