What is a class and an instance?
To go over what we have just done and to explain the concept of a class and an instance a bit more clearly, let's take a look at the following screenshot and explanation:
A class acts as a blueprint to create objects from. In this example, we created a class called Car. This Car class acts as a blueprint to build instances of cars from. So, because it's a blueprint, we define what each car has in the class—these are called member variables (in our case, that's a model, a brand, and a color). We also define actions that a car can perform and what a car can do, and we call these methods! In our car example, we have defined that a car can start, stop, and also accelerate.
Note that there is one special member variable, the count variable, which we declared as static, which means that this is a class variable and not a member variable. This means that contrary to member variables (where each instance will have its own values), the class variable (static) will not get its own instance and will be the same for all objects (instances) created out of the class! In this example, you'll see that in the constructor, we declare count++, which will increment this count variable each time a new instance is created in memory.
An instance of a class is what we call an object. Each object, when it's instantiated (created) from the class, gets its own little space in the memory, which we can access by the name we give it at the time of creation. In the example, we create three separate instances/objects from the Car class, called blueCar, redCar, and yellowCar. Our constructor requires us to pass parameters to set the brand, the model, and the color when a new instance for each car is created. So, when creating our redCar object (instance), we passed Renault (as a brand), Clio (as a model), and red (as the color). We did this for each object.
By doing that, we can now use each object to output their member variables or to call their methods, by using dot notation. Dot notation is how you access the fields and/or methods of an object. You use the name (the reference to the object in the memory) followed by a . (dot), and then the name of the variable or method you want to call, like blueCar.model, which will give you the value of the model variable of the blueCar instance from the memory.
This should look familiar to you. Think back to Chapter 3, Declarative Automation, in the first part about formulas. How do you access the value of the email field of an account in Salesforce? That's right: by using the Account.Email method.
Now, everything should start to fall into place. This is why I mentioned in the earlier chapters that each custom object you create (like our Movie__c object) is immediately available for you to use in Apex code, as they are classes from which you create objects (instances). In fact, in Salesforce, they are called sObjects, which helps them make the distinction between classes that represent real objects from within the Salesforce database, such as Account, Lead, or Movie__c, and classes you've created yourself (that do not represent real database objects, but just act as blueprints to use in your code with custom logic), such as our MovieSelector class.
I hope this makes things a bit clearer now. We will go more in-depth on these concepts later on in the book (in Chapter 5, Apex - Beyond the Basics, in the Classes and interfaces section).