Abstract, Virtual, Interface in APEX – Part I

Hello Devs,
Today I would like to give you a brief description of Abstract, Virtual, and Interface in APEX. We will try to understand the difference between them and figure out when we should use each of them.

Let’s begin!


Interface

Description
  • To create interface we need to use interface keyword.
  • Interface can provide a layer of abstraction to your code.
  • Interface is an apex class that can contain only method signature, as a result, the body of each method must be empty.
  • An apex class that is using the interface must implement all methods listed in the interface.
  • Interface separates the specific method declaration from its implementation. Therefore you can have different implementation for the same method. Concept behind Interface is that you can change implementation without changing your whole code. Consequently, method signature (return type, parameters) are always the same.
  • Interface can be treated as a new data type. In Apex we have a few predefined interfaces like String, Integer, Double, etc. In other words implementation of those methods can be change (by Salesforce) without changes in our code – that’s the power of interface!
    e.g.: String.isBlank(‘Test’);
    We know method signature (public static Boolean isBlank(String inputString)), but we don’t know implementation layer.
Code Structure
// Interface
public interface Employee {
   // Method's signature
   Double increaseEmployeeSallary(Double currentSalarry);
}
//Example A
public class CompanyAEmployee implements Employee {
   public Double increaseEmployeeSallary(Double currentSalarry) {
      return currentSalarry * 1.1;
   }
}
//Example B
public class CompanyBEmployee implements Employee {
   public Double increaseEmployeeSallary(Double currentSalarry) {
      return currentSalarry * 1.2;
   } 
}
// Because each class implements Employee interface, we can do something like that:
Employee employeeA = new CompanyAEmployee();
Employee employeeB = new CompanyBEmployee();

employeeA.increaseEmployeeSallary(1000.0); //1100
employeeB.increaseEmployeeSallary(1000.0); //1200
Use Cases
  • We program to interfaces, not implementations!
  • Your class can implement a few interfaces! As a result, you allow your class to have different behaviour.
  • When you need to guarantee specific logic.
  • For instance, you can provide interface to another team, before you will start working on implementation for particular methods. Therefore, they don’t need to wait for your code. No blockers anymore!
  • When you need to create new data types with some set of methods, but with different implementation.
  • Code is easier to change when it depends only from interfaces. Doesn’t have reference to specific classes, but to interface.
  • A good example of it are Database.Batchable, Queueable, Schedulable interfaces. This way Salesforce force as to implement specific methods.
  • Good choice if the API will not change for a while.
  • Limitation! It’s hard to add new method to interface, because all classes, which implement that interface needs to be changed (updated about new method).

Abstract

Description
  • To create abstract class, we need to use abstract definition modifier.
  • Allow to extend the child class.
  • Abstract class can contain methods signed as abstract, to clarify, it is a method that has only a signature (body is not defined).
  • Child class must implement all methods declared as abstract!
  • Abstract class can also include other methods, which have the logic.
    To allow child class access those methods use protected or public keyword.
  • Cannot be initialize directly: new TestAbstractClass():
  • Abstract class can contain both virtual and abstract methods.
  • Abstract class is some kind of “partial” class.
    Therefore, some methods are implemented, some needs to be implemented by child class.
  • virtual methods can be override, but this is not mandatory.
  • We can have different signatures for our methods:
    • private – child class doesn’t have access to method signed as private.
    • protected – child class has access to parent class method, but any other class doesn’t have access.
    • public – In other words, making method accessible by any other class.
Code Structure
//Abstract Parent class
public abstract class TestAbstractClass {

    protected String test1;
    public String test2;

    TestAbstractClass() {}

    TestAbstractClass(String test1, String test2) {
       this.test1 = test1;
       this.test2 = test2;
    }

    abstract public String myAbstractMethod();

    public virtual String myVirtualMethod() {
       return 'virtual method from abstract class';
    }

    private String myPrivateMethod() {
       return 'private method from abstract class';
    }

    protected String myProtectedMethod() {
       return 'protected method from abstract class';
    }

    public String myPublicMethod() {
       return 'public method from abstract class';
    }
}
//Child class
public class ExampleClass extends TestAbstractClass {

   ExampleClass(String test1, String test2) {
      //You can use abstract class constructor using super. Remember! Abstract class cannot be initialized, so this is the only scenario when you can use abstract class constructor!
      super(test1, test2);
   }

   public String myAbstractMethod() {
      return 'Abstract method implemented in child class!';
   }

   public override String myVirtualMethod() {
      return 'Virtual method overridden in child class!';
   }   

   public String invokeMethodFromAbstractClass() {
      String methods = '';
      methods += myPrivateMethod();//error, private method is not accessible in child class
      methods += myProtectedMethod();
      methods += myPublicMethod();

      return methods; //protected method from abstract class public method from abstract class
   }
}
ExampleClass example = new ExampleClass('Hello', 'World');
System.debug(example.test1); //error. Property test1 can be accessed only in child class.
System.debug(example.test2); //output: 'World';
System.debug(example.myAbstractMethod()); //output: 'Abstract method implemented in child class!'
System.debug(example.myVirtualMethod()); //output: 'Virtual method overridden in child class!'
System.debug(example.myPrivateMethod()); //error. It can be used only in parent class
System.debug(example.myProtectedMethod()); //error. It can be used only in parent and child classes
System.debug(example.myPublicMethod()); //output: 'public method from abstract class'

TestAbstractClass abstractClass = new TestAbstractClass();//error. Abstract class cannot be initialized 
Use Cases
  • When your classes can have common methods, with similar logic.
  • When there is a possibility that some new methods will be added in future.
  • There is requirement, that some logic must be class specific. eg. CompanyA, CompanyB can have the same pay() implementation, but different for increaseSalary(). You can just mark increaseSalary method as abstract.
  • Abstract class allows you in easy way to update logic for all child classes. The only thing you need to do is just to change implementation in abstract class.

Virtual

Description
  • To create virtual class, we need to use virtual definition modifier.
  • You can extend a class to provide more sophisticated behaviour.
  • Class that extends another class inherits all the methods and properties of the extended class.
  • Methods declared as virtual can be override.
    In other words, overriding a virtual method allows you to provide a different implementation for an existing method.
  • A class can only extend one other class, but it can implement more than one interface.
  • Virtual class can be initialize directly new TestVirtualClass();
  • You can use only virtual methods.
  • Virtual class is some kind of “full” class.
    All methods are implemented, but can be override by child class.
Code Structure
//Parent Virtual Class
private virtual class TestVirtualClass {
   
   protected String test1;
   public String test2;

   TestVirtualClass() {}

   TestVitrualClass(Strint test1, String test2) {
       this.test1 = test1;
       this.test2 = test2;
   }

   public virtual String myVirtualMethod() {
      return 'virtual method from virtual class';
   }

   private String myPrivateMethod() {
      return 'private method from virtual class';
   }

   protected String myProtectedMethod() {
      return 'protected method from virtual class';
   }

   public String myPublicMethod() {
      return 'public method from virtual class';
   }
}
//Child class
public class ExampleClass extends TestVirtualClass {
  
   ExampleClass(String test1, String test2) {
      //You can use virtual class constructor using super. 
      super(test1, test2);
   }

   public override String myVirtualMethod() {
      return 'Virtual method overridden in child class!';
   }   

   public String invokeMethodFromAbstractClass() {
      String methods = '';
      methods += myPrivateMethod();//error, private method is not accessible in child class
      methods += myProtectedMethod()
      methods += myPublicMethod();

      return methods; //protected method from abstract class public method from abstract class
   }
}
ExampleClass example = new ExampleClass('Hello', 'World');
System.debug(example.test1); //error. Property test1 can be accessed only in child class.
System.debug(example.test2); //output: 'World';
System.debug(example.myVirtualMethod()); //output: 'Virtual method overridden in child class!'
System.debug(example.myPrivateMethod()); //error. It can be used only in parent class
System.debug(example.myProtectedMethod()); //error. It can be used only in parent and child classes
System.debug(example.myPublicMethod()); //output: 'public method from virtual class'

TestVirtualClass virtualClass = new TestVirtualClass();
System.debug(virtualClass.myVirtualMethod()); //output: 'virtual method from virtual class' 
System.debug(virtualClass.myPrivateMethod()); ////error. It can be used only in parent class
System.debug(virtualClass.myProtectedMethod()); //error. It can be used only in parent and child classes
System.debug(virtualClass.myPublicMethod()); //output: public method from virtual class'
Use Cases
  • When your classes can have common methods, with similar logic.
  • When you should have possibility to initialize parent class with new. eg. class needs to be used directly.
  • For instance, you have basic logic, but some methods can be overridden by child class. (virtual methods)
  • Virtual class is an easy way to update all child methods, without multiple changes in code. (Just update virtual class)

Conclusion

Interface, Abstract and Virtual class are different methods to make your code more generic, reusable and clear.
Interface gives you another layer of abstraction and it makes it easier to change your implementation.
Abstract class allows you to force developer who is using your class, to implement some methods.
Above all, Virtual is the lightest solution, which gives you the possibility to override some method provided by parent class.

Was this helpful? Check out our other great posts here.


Resources

4.9 14 votes
Article Rating
Subscribe
Notify of
guest
2 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
trackback

[…] ┬áToday I would like to expand the Abstract, Virtual, Interface subject which was described in Abstract, Virtual, Interface in APEX – Part I Let’s […]

Close Menu
2
0
Would love your thoughts, please comment.x
()
x