Menu
subscribe our youtube channel popup

Virtual Classes and Virtual Methods in Apex

Salesforce Apex, a robust programming language designed for custom development and advanced business logic on the Salesforce platform, provides developers with the tools to build flexible, reusable, and scalable code. Among them are virtual classes and virtual methods. In this article, we’ll explore what virtual classes and methods are, their significance, and how they can be applied in real-world scenarios. Join us to learn about Virtual Classes and Virtual Methods in Apex.

What Are Virtual Classes and Methods?

In Salesforce Apex, a virtual class serves as a base class intended for extension by child classes. It allows methods marked as virtual to be overridden and tailored with specific behaviour in those child classes. This facilitates polymorphism, enabling the same method call to produce different outcomes based on the object type in use.

Virtual Classes:

  • A class marked as ‘virtual’ can be extended by another class.
  • This is similar to the abstract class, but the difference is that a virtual class can have fully implemented methods, whereas abstract classes require at least one abstract method.

Virtual Methods:

  • A method declared as ‘virtual’ allows its implementation to be overridden in a subclass.
  • This is useful for customizing behaviour in derived classes while maintaining a common interface.

Virtual Class

//virtual class
public virtual class BaseClass {
    //virtual method
    public virtual void displayMessage() {
        System.debug('Base Class Message');
    }
}
//extending the virtual class
public class DerivedClass extends BaseClass {
    //overriding the virtual method
    public override void displayMessage() {
        System.debug('Derived Class Message');
    }
}

Why Use Virtual Classes and Methods?

  • Modularity: Code is organized into logical units, making it easier to maintain and debug.
  • Reusability: Common functionality can be written once in a base class and reused in multiple derived classes.
  • Extensibility: Developers can extend base classes to implement specific behaviours without modifying the original class.
  • Polymorphism: You can use base class references to handle derived class objects, making your code more dynamic and flexible.
  • Framework Development: They are ideal for creating frameworks where developers can extend functionality as needed.
FREE Salesforce Developer Training
FREE Salesforce Developer Training

Example Scenario: A Payment Processing Framework

Let’s consider an example of a payment processing system for an e-commerce app. The company accepts different payment methods such as Credit Card and PayPal. To handle these methods, let’s create a reusable and extensible payment framework using virtual classes and methods.

Scenario Overview:

Customers initiate the payment process by selecting their preferred payment method at checkout.

Fields and Objects Required:

ObjectFieldDescription
Payment A custom object to store payment detailsAmountThe amount to be processed
Payment MethodPayment method selected (Credit Card or PayPal)
StatusStatus of the payment
Order A custom object representing the customer’s orderOrder TotalTotal order amount
Payment StatusOverall payment status for the order

Base Virtual Class

The base class defines the common structure for all payment methods.

public virtual class PaymentProcessor {
    public virtual void processPayment(Decimal amount) {
        System.debug('Processing payment of: ' + amount);
    }
}

This class provides a default implementation for processing payments. Derived classes will override this method to implement specific logic for each payment type.

Derived Classes:

Each derived class implements its specific payment logic.

public class CreditCardPayment extends PaymentProcessor {
    public override void processPayment(Decimal amount) {
        System.debug('Processing Credit Card payment of: ' + amount);

        //logic for credit card payment integration here
        System.debug('Credit Card Payment Successful!');
    }
}
public class PayPalPayment extends PaymentProcessor {
    public override void processPayment(Decimal amount) {
        System.debug('Processing PayPal payment of: ' + amount);

        //logic for credit card payment integration here
        System.debug('PayPal Payment Successful!');
    }
}

Handler Class – Using Polymorphism:

Polymorphism allows the framework to dynamically handle different payment methods without changing the core logic.

public class PaymentHandler {
    public void processAnyPayment(PaymentProcessor paymentProcessor, Decimal amount) {
        paymentProcessor.processPayment(amount);
    }
}
//usage – in an apex anonymous window
PaymentHandler handler = new PaymentHandler();
PaymentProcessor creditCard = new CreditCardPayment();
PaymentProcessor payPal = new PayPalPayment();

handler.processAnyPayment(creditCard, 100.00);
handler.processAnyPayment(payPal, 200.00);

 
Output:

Hence, when a customer selects a payment method on the e-commerce app, the Salesforce org uses this framework to handle the payment by passing the appropriate PaymentProcessor subclass to the PaymentHandler. The processPayment method is invoked, and the specific logic for the selected payment type (Credit Card or PayPal) is executed.

By building the above framework, we achieve the following:

  • Modularity – Payment logic is separated into distinct classes.
  • Reusability – The base class provides common functionality.
  • Scalability – Adding a new payment method (e.g., Apple Pay) only requires creating a new subclass without modifying existing code.
  • Maintainability – Debugging and testing become simpler with a clear separation of logic.

When to Use Virtual Classes and Methods

  • Use virtual classes when you want to provide a base implementation that other classes can customize by overriding specific methods. This is particularly beneficial in scenarios where multiple subclasses share common functionality but require unique behaviour for certain operations.
  • In applications with complex logic or multiple related components, virtual classes help organize code by grouping related functionalities together while allowing for easy customization.
  • When creating a framework or library where you want to provide default behaviour but still allow users to extend and modify it according to their needs, virtual classes are ideal.
  • If you need a class that should be instantiated directly while also allowing for method overriding, a virtual class is appropriate.

When to Avoid Virtual Classes and Methods

  • If the system has a simple and fixed structure, virtual methods may add unnecessary complexity.
  • Overusing inheritance in performance-critical code may impact execution time slightly due to method lookups.
  • If the functionality can be achieved using declarative tools like Flows or Process Builder, avoid overcomplicating with Apex.

Conclusion

Virtual classes and methods in Salesforce Apex are powerful tools for building flexible and scalable solutions. By enabling inheritance and polymorphism, they allow developers to write clean, reusable, and maintainable code. In our payment processing example, we’ve demonstrated how to build a modular and extensible framework that can adapt to new requirements. Understanding when and how to use these features effectively is key to mastering Apex and delivering high-quality Salesforce applications. With this foundation, you can implement virtual classes and methods in your projects, ensuring your code remains modular and adaptable to future needs.

Sheima Latha J
Sheima Latha J
Articles: 20

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *