Mastering Object-Oriented Programming in Apex : A Comprehensive Guide

Mastering Object-Oriented Programming in Apex

Object-Oriented Programming in Apex

Object-Oriented Programming in Apex refers to the use of Objects, as real world entities. It is a common concept used in programming languages like C, C++, Java, and is pivotal to Apex as well.

We use classes to define these objects binding data variables(properties) and functions(behavior) together. It allows for the modularization of code and promotes code reuse, which is important for building scalable applications.

Four pillars of OOPs are as follows and we will talk more about it later in this chapter:

  1. Encapsulation
  2. Abstraction
  3. Inheritance
  4. Polymorphism

Encapsulation in Apex

Imagine a capsule, to understand this. As a capsule holds its medicinal properties and functions, put together in a capsule. Similarly in Apex, all properties and functions of an object can be bundled together with the help of classes. This is behavior is known as Encapsulation.

Encapsulation in Apex

Classes and Objects

  • Class: A blueprint that defines the structure and behavior (attributes and methods) of an object.
  • Object: An instance of a class that holds actual data. If the class is the template, the object is the real-world version of that template.

Syntax for Defining Classes and Creating Objects

Lets start with a simple class definition:

public class Car {
public String company;
public String model;
public void displayMyCarInfo() {
System.debug('Company : ' + company + ', Model: ' + model);
}
}
  • public class Car: defines a class named Car.
  • public String company and public String model: are attributes or fields of the class.
  • public void displayMyCarInfo(): A method of the class

To instantiate an object of this class:

Car myCar = new Car();
myCar.company = 'Hyundai';
myCar.model = 'Model S';
myCar.displayMyCarInfo();
  • new Car(): This creates an instance of the Car class.
  • myCar: A reference variable pointing to that object.

In this example, myCar is an object holding the actual data record (Hyundai, Model S).

Why Use Classes and Objects?

  • Modularity: We can break down complex programs into smaller, manageable classes. For example think of this chapter(a class) for learning Apex Programming(a complex program).
  • Reusability: Once a class is defined, it can be used multiple times by creating different objects thus making it reusable.

Constructors

A constructor is a special method that is automatically invoked when an object of the class is created. Its purpose is to initialize the object’s state (assign values to attributes). Defining constructors are optional for a class.

Constructor for the above example:
public class Car {
public String company;
public String model;

// Constructor
public Car(String company, String model) {
this.company = company;
this.model = model;
}


public void displayMyCarInfo() {
System.debug('Company : ' + company + ', Model: ' + model);
}
}

Now, when we create a new Car object we can choose to instantiate the attributes along side:

Car myCar = new Car('Hyundai', 'Model S');

This automatically initializes the object myCar to ‘Hyundai’ and model to ‘Model S’.

Methods

A method is a block of code that performs a specific task. In Apex, methods are defined using the following structure:

public returnType methodName(parameters) {
// Method body
}

You’ve already seen the displayMyCarInfo method earlier. Methods can return values or simply perform operations. When they don’t return something the returnType is ‘void‘.

Attributes

Attributes (or fields) store the state of an object. In our examples, company and model are attributes that hold data about the car.


Abstraction in Apex

Now to understand Abstraction, imagine a gaming controller. When we play a game using this, we only see some basic buttons to perform certain actions like move up, down, jump, etc. We we don’t exactly know the ‘how’ part, as in what happens inside the casing of the controller remains hidden to us. Similarly, apex classes can hide the internal state of the object or some sensitive piece of code/information and expose only the necessary functions. This property is known as abstraction. We can achieve this with the help of access modifiers to control the visibility and accessibility of any class, method, and variable.

Abstraction in Apex

Access Modifiers (public, private, global, protected) in Apex

In Apex, access modifiers control the level of abstraction for a method, class or variable.

Types of Access Modifiers:

  1. Public: The class, method, or variable is accessible anywhere in the Apex code.
  2. Private: Accessible only within the class in which it is defined.
  3. Protected: Accessible to the defining class and any child classes that inherit from it.
  4. Global: Accessible in any context, even outside the current namespace (used sparingly).

Example:

public class Car {
private String engineType; //Only accessible within car class
protected Integer selfDriveMode; //Accessible in child classes
}

Setter Getter Methods in Apex

Example:
public class Car {
private String make; // Only accessible within this class
public String model; // Accessible from anywhere

public void setMake(String make) {
this.make = make; // Setter to modify private variable
}

public String getMake() {
return make; // Getter to access private variable
}
}

In the above code:

  • private String make: This ensures make is only accessible through getter/setter methods.
  • public String model: This field is open for direct access from outside the class.

Key Takeaway: Use private to protect sensitive data, and public when you want to expose it for wider use. protected is ideal in scenarios involving inheritance.

Static and Instance Methods and Variables

Static methods belong to the class itself, while instance methods require specific objects to operate on.

Static:

  • A static method or variable is shared across all instances of the class.
  • They are initialized only when a class is loaded and hereby are static in nature.
  • They are used as a utility method and never depends on the value of an instance member variable.
  • They are static only within the scope of the Apex transaction. It’s not static across the server and is reset across transaction boundaries.
Example:
public class Car {
public static Integer noOfWheels = 4;

public Integer maxAcc;
public static void DisplayMaxSpeed(Integer speed) {
System.debug('Speed at max ' + speed);
}
}

We can access these static variables and methods without creating an instance of the class:

// Calling static method
System.debug(Car.DisplayMaxSpeed(250));

All triggers triggered by a single transaction, can communicate with each other by viewing and updating static variables in a related class. But it doesn’t retain its value between different trigger contexts(update, delete, insert, etc) within the same transaction. A recursive trigger hereby can use the value of a static variable to determine when to exit the transaction.

Instance:

An instance method or variable is tied to a specific object and each object has its own copy of instance variables.

  • They are associated with a particular object.
  • They have no definition modifier.
  • They are created with every object instantiated from the class in which they’re declared.

In above example, we cannot use maxAcc variable without creating an object for the class Car.

// instance variable
Car carObj1 = New Car();
Car carObj2 = New Car();
carObj1.maxAcc = 225;
carObj2.maxAcc = 122;

Its helpful to recognize the static and instance memory allocation of variables as below:


Inheritance in Apex

To understand Inheritance, we can think of the meaning of inheritance. As humans we inherit some of our qualities or habits from our parents, apart from our own uniqueness. Inheritance in Apex in a similar fashion, allows a new class (subclass) to inherit properties and behaviors from an existing class (virtual or abstract). Inheritance promotes code reuse. The subclass can also have additional properties and methods of its own. There are two main keywords here to understand, extends and implements.

Inheritance in Apex

Extends keyword

  • Extends‘ is used to extend the functionality of the parent class to the subclass. 
  • One class can extend only one class to avoid any confusions related to methods and functionalities.
  • Extends help define a new class inheriting the base class. We can choose to override the inherited methods.

Implements keyword

  • Implements‘ is used to implement the functionality of an interface. An interface is a special type of class with only abstract methods.
  • Accessing these interface methods, require the interface to be implemented by another class and implementing(defining) its methods.
  • As interfaces do not have any method implementations, we can implement n number of interfaces at a time.

Note : A class can extend one class and can implement any number of interfaces. While an interface can extend any number of interfaces at a time and implement none.

In Apex, we cant inherit virtual as well as abstract classes. The difference between the both being virtual has basic logic, that can be overridden by the child class while abstract does not contain any logic, and must be implemented. We can choose to use any based on our requirement.

Abstract Class in Apex

An abstract class cannot stand on their own (cant be instantiated) and can contain abstract methods that must be implemented by child classes. Abstract methods can only be signatures, and must be implemented in child classes

Example

public abstract class Shape {
public abstract Double area();
}


public class Circle extends Shape {
public Double radius;

public Circle(Double radius) {
this.radius = radius;
}

public override Double area() {
return 3.14 * radius * radius;
}
}

Virtual Class in Apex

Virtual classes can have virtual or regular methods, but they can’t have abstract methods. Virtual classes contain basic logic that can be accessed by child classes.  Extending class can override the existing virtual methods by using the override keyword in the method definition(exhibiting Polymorphism).

Example

The virtual definition modifier allows extension and overrides in Apex.

public virtual class Vehicle {
public Integer speed;
public virtual void makeNoise() {
System.debug('Beep beep! Honk honk!');
}
public void move() {
System.debug('Vehicle is moving at ' + speed + ' mph'); }
}

public class Car extends Vehicle {
public String make;
public String model;


// we can only override virtual and abstract methods
public override void makeNoise() {
System.debug('Vroom Vroom!');
}
}


Car myCar = new Car();
myCar.makeNoise(); // Output: Vroom Vroom!
myCar.move(); // Vehicle is moving at null mph

The Car class inherits the speed attribute and move() method from the Vehicle class.

We can also create a Car object and assign it to the Vehicle variable, it is also a completely valid statement. It also inherits the methods and variables as below.

Vehicle myVehicle = new Car(); 
myVehicle.makeNoise(); // Output: Vroom Vroom!
myVehicle.move(); // Vehicle is moving at null mph

Interfaces in Apex

Interfaces are like contracts that the implementing classes must adhere to. An interface defines methods that implementing classes must contain but doesn’t provide any method implementations just method signatures. It is a convenient way of enforcing a layout of common functions onto all the classes inheriting the interface, that they must define these functions.

Example

public interface Shape {
void calculateArea();
}


public class Circle implements Shape {
public void calculateArea() {
// Circle area calculation logic
}
}

The Circle class must implement the calculateArea() method defined in the Shape interface.


Polymorphism in Apex

Polymorphism means having several forms i.e. the ability of being represented in multiple forms. In Apex, we see polymorphism with method overriding and method overloading. Overloading happens at compile-time while Overriding happens at runtime. Polymorphism allows for methods to have different implementations based on the object it is acting upon and the parameter passed.

Method overloading in Apex

Method overloading in Apex allows the creation of multiple methods with the same name but different parameters. 

Example:
public static string kebabString(string s1){
return s1;
}
public static string kebabString(string s1,String s2){
String subString = s1+'-'+s2;
return subString;
}

In Apex, all methods and classes are final by default. Private and final methods can be overloaded but they cannot be overridden. So to override a class or a method we have to used virtual and override keyword

Method overriding in Apex

To override a method in Apex, you can use the override keyword in the child class.

Example:
public class Vehicle {
public void move() {
System.debug('Vehicle is moving');
}
}

public class Car extends Vehicle {
public override void move() {
System.debug('Car is driving');
}
}

Vehicle myVehicle = new Car();
myVehicle.move(); // Output: "Car is driving"

The method move() behaves differently depending on whether the object is a Vehicle or a Car.


Conclusion

Understanding classes, objects, and OOP principles is vital for writing efficient Apex code. By applying these concepts, you can write modular, reusable, and scalable code in Salesforce. This article has walked you through key aspects such as constructors, access modifiers, abstract classes, interfaces, and static and instance methods and variables.

As you continue your journey with Apex, keep practicing with these concepts and it will become intuitive. Happy coding!

Leave a Reply

error: Content is protected !!