What's the difference between Abstract class and Virtual Class
tl;dr:
Practically speaking, there isn't much difference. Don't worry about it too much. I tend to use abstract
more often.
long version
The difference has historically been quite subtle.
- Both
virtual
andabtract
classes allow you to extend the class (i.e. create child classes that inherit non-private methods and variables) - A
virtual
class can be instantiated directly, whereas anabstract
class cannot - Both
virtual
andabstract
classes can containvirtual
methods (virtual
methods can have a default implementation that is inherited by child classes, whereasabstract
methods can only be signatures, and must be implemented in child classes) - Only
abstract
classes may containabstract
methods
In practice, I haven't seen much practical difference between the two. The abstract
and virtual
modifiers, in my mind, are more important for methods (as opposed to classes).
If you're going to use a class that's either abstract
or virtual
, I've found that I'm more likely to be using that class as more of a contract (i.e. when you use this class, we guarantee that variables a
, b
, and c
will be available for use, along with methods x
, y
, and z
), rather than a specialization that is used apart, distinctly, from its parent class.
This mostly comes down to the philosophy of object-oriented design that I have learned as part of my professional career. To put it into a single sentence: If you're relying on something having a specific implementation (i.e. you need to use a square
or a rectangle
instead of a more general parallelogram
), then you can probably improve your solution.
The general idea is that by relying on contracts rather than implementations, your code is more resistant to change. Put another way, by relying on contracts, a change to a specific implementation of that contract is contained to one or two classes (as opposed to making a change in one class ending up requiring a change to many other classes).
So for that goal (relying on a contract more than an implementation), I find myself using abstract
classes more often because I tend to want the consumers of my code to use specific, specialized implementations (to suit the task at hand) rather than a general "catch-all" implementation. To that end, abstract
, with it's inability to be directly constructed, is more useful to me.
Abstract classes allow you to define "partial" classes. They implement some sort of algorithm that can be used by other classes, but do not represent a full implementation by themselves. For example, my AWS example provides a class that handles calculating parameters, etc (over 200 lines of default functionality), but does not directly do anything with AWS; the remainder is handled by child classes to connect to a specific service. Note that abstract classes could be implemented by interfaces or helper classes, but make the code more compact and generally legible.
Virtual classes allow you to define "full" classes. They implement all of the necessary functionality to operate on their own, but can be extended by child classes in order to allow customization of its behavior. This is far less common in every day Apex Code than abstract classes, but is useful when you have large classes that provide tons of default functionality, but may require overriding just one or two methods. In Java, these are used all over the place, for example, a WindowAdapter that can listen to about a dozen events, but can have just one method overridden so the developer doesn't have to write implementations for all of the methods.
Unlike interfaces and abstract methods, virtual classes allow you to override just one single method if you want, without having to implement all of the methods. For example, a Trigger Handler factory might use a virtual class to provide default methods (e.g. beforeInsert, afterInsert, beforeUpdate...), but allow the developer to override just one method instead of a dozen.
The Apex Class Definition resource from the Apex Developer Guide may provide some illumination.
In summary, virtual
classes permits subclassing and method overriding. However, a virtual
class does implement functionality itself and can be instantiated and used directly.
Conversely, abstract
classes must be subclassed and have methods overridden to provide functionality. abstract
classes cannot be instantiated or used themselves; they are more fully "abstract base classes".