Create Apex Class and Object

Create Apex Class and Object

Create the following class:

public class Fridge {
    public String modelNumber;
    public Integer numberInStock;

    public void updateStock(Integer justSold) {
        numberInStock = numberInStock - justSold;
    }
}

The class has two member variables, modelNumber and numberInStock, and one method, updateStock.

The void type indicates that the updateStock method doesn’t return a value.

Execute the following in the Developer Console:

Fridge myFridge = new Fridge();
myFridge.modelNumber = 'MX-O';
myFridge.numberInStock = 100;
myFridge.updateStock(20);

Fridge myOtherFridge = new Fridge();
myOtherFridge.modelNumber = 'MX-Y';
myOtherFridge.numberInStock = 50;

System.debug('myFridge.numberInStock=' + myFridge.numberInStock);
System.debug('myOtherFridge.numberInStock=' + myOtherFridge.numberInStock);

This creates a new instance of the Fridge class, called myFridge, which is an object. It sets the values of the variables in the object, and then calls the updateStock method, passing in an argument of value 20. When this executes, the updateStock instance method will subtract the argument from the numberInStock value. Next, it creates another instance of the Fridge class and sets its stock number to 50. When it finally outputs the values, it displays 80 and 50.

Private Modifiers

The class, class methods, and member variables were all declared using the public keyword until now. This is an access modifier that ensures other Apex classes also have access to the class, methods, and variables. Sometimes, you might want to hide access for other Apex classes.

Let’s modify our Fridge class to use private modifiers for the member variables.

  1. Modify the Fridge class and change the modifier of both variables to private:
private String modelNumber;
private Integer numberInStock;
  1. Click Quick Save.
  1. Execute the following in the Developer Console:
Fridge myFridge = new Fridge();
myFridge.modelNumber = 'MX-EO';

You’ll receive an error warning: Variable is not visible: modelNumber. The variable modelNumber is now only accessible from within the class—a good practice.

  1. To provide access to it, define a new public method that can be called to set its value and another to get its value. Add the following inside the class body of Fridge.
public void setModelNumber(String theModelNumber) {    
    modelNumber = theModelNumber;
}

public String getModelNumber() {
    return modelNumber;
}
  1. Click Quick Save.
  2. Execute the following:
Fridge myFridge = new Fridge();
myFridge.setModelNumber('MX-EO');
System.debug(myFridge.getModelNumber());

This will execute properly. The call to the setModelNumber method passes in a string which sets the modelNumber value of the myFridge instance variable. The call to the getModelNumber method retrieves the model number, which is passed to the System.debug system method for writing it to the debug output.

Constructors

Apex provides a default constructor for each class you create. For example, you were able to create an instance of the Fridge class by calling new Fridge(), even though you didn’t define the Fridge constructor yourself. However, the Fridge instance in this case has all its member variables set to null because all uninitialized variables in Apex are null. Sometimes you might want to provide specific initial values, for example, number in stock should be 0 and the model number should be a generic number. This is when you’ll want to write your own constructor. Also, it’s often useful to have a constructor that takes parameters so you can initialize the member variables from the passed in argument values.

Try adding two constructors, one without parameters and one with parameters.

  1. Add the following to your Fridge class:
public Fridge() {
    modelNumber = 'XX-XX';
    numberInStock = 0;
}

public Fridge(String theModelNumber, Integer theNumberInStock) {
    modelNumber = theModelNumber;
    numberInStock = theNumberInStock;
}

The constructor looks like a method, except it has the same name as the class itself, and no return value.

  1. You can now create an instance and set the default values all at once using the second constructor you’ve added. Execute the following:
Fridge myFridge  = new Fridge('MX-EO', 100);
System.debug (myFridge.getModelNumber());

This will output ‘MX-EO’. You’ll often see classes with a variety of constructors that aid object creation.

Static Variables, Constants, and Methods

The variables and methods you’ve created so far are instance methods and variables, which means you have to first create an instance of the class to use the modelNumber and numberInStock variables. Each individual instance has its own copy of instance variables, and the instance methods can access these variables. There are times when you need to have a member variable whose value is available to all instances, for example, a stock threshold variable whose value is shared with all instances of the Fridge class, and any update made by one instance will be visible to all other instances. This is when you need to create a static variable. Static variables are associated with the class and not the instance and you can access them without instantiating the class.

You can also define static methods which are associated with the class, not the instance. Typically, utility methods that don’t depend on the state of an instance are good candidates for being static.

  1. Modify the Fridge class by adding the following static variable:
public static Integer stockThreshold = 5;
  1. Execute the following in the Developer Console:
  System.debug ( Fridge.stockThreshold );

This will output 5. Note how you didn’t have to create an instance of the Fridge class using the new operator. You just accessed the variable on the class.

  1. You can also change the value of this static variable by accessing it through the class name.
// Modify the static stock threshold value
Fridge.stockThreshold = 4;
System.debug ( Fridge.stockThreshold );

This will write 4 to the output.

  1. Sometimes you want to declare a variable as being a constant—something that won’t change. You can use the final keyword to do this in Apex; it indicates that the variable might be assigned to a value no more than once. Modify the static variable you just declared to as follows:
public static final Integer STOCK_THRESHOLD = 5;

You can still output the value of the field, for example, Fridge.STOCK_THRESHOLD; will work, but you can now not assign any other value to the field, for example, Fridge.STOCK_THRESHOLD = 3; won’t work.

  1. Let’s define a static class method that prints out the values of a given object that gets passed in as an argument. This will be a great help for debugging. Add a new method to the Fridge class:
public static void toDebug(Fridge aFridge) {
    System.debug ('ModelNumber = ' + aFridge.modelNumber);   
    System.debug ('Number in Stock = ' + aFridge.numberInStock);
}
  1. Test out this new method by calling it in the Developer Console and passing in a Fridge instance:
Fridge myFridge = new Fridge('MX-Y', 200);
Fridge.toDebug(myFridge);

This is the output you’ll get in the Developer Console.

Output of the static toDebug method

You now have an easy way to dump any object you create to the Developer Console!

Interfaces

An interface is a named set of method signatures (the return and parameter definitions), but without any implementation.  Interfaces provide a layer of abstraction to your code. They separate the specific implementation of a method from the declaration for that method. This way, you can have different implementations of a method based on your specific application. For example, a fridge is a type of kitchen appliance, and so is a toaster. Since every kitchen appliance has a model number, the corresponding interface can have a getModelNumber method. However, the format of the model number is different for different appliances. The Fridge class and the Toaster class can implement this method such that they return different formats for the model number.

Interfaces can be handy—they specify a sort of contract. If any class implements an interface, you can be guaranteed that the methods in the interface will appear in the class. Many different classes can implement the same interface.

Try it out by creating an interface that is implemented by the Fridge and Toaster classes.

  1. Create an interface in the same way that you create a class:
public interface KitchenUtility {
  String getModelNumber();
}
  1. Modify your Fridge class to implement this interface. Simply add the words in bold to the definition of the class on the first line.
public class Fridge implements KitchenUtility {
  1. Now define a new class called Toaster that also implements the KitchenUtility interface.
public class Toaster implements KitchenUtility {
   private String modelNumber;

   public String getModelNumber() {
      return 'T' + modelNumber;
   }

}

Because both the Toaster and Fridge classes implement the same interface, they will both have a getModelNumber method. You can now treat any instance of Toaster or Fridge as a KitchenUtility.

  1. The following example creates an instance of a Fridge and Toaster. It then creates an array of KitchenUtility objects using these two objects and treating them as KitchenUtility instances.
Fridge f = new Fridge('MX', 200);
Toaster t = new Toaster();

KitchenUtility [] utilities = new KitchenUtility[] { f, t };

String model = utilities[0].getModelNumber();
System.debug(model);