In its simplest form, a class is a container of code and data much like a module. But unlike a module, a class provides better code reuse. Classes are the fundamental building blocks of object-oriented programming.
Classes offer many benefits, including:
- Reusable Code: When you directly add code to a PushButton on a Window to customize its behavior, you can only use that code with that one PushButton. If you want to use the same code with another PushButton, you need to copy the code and then make changes to the code in case it refers to the original PushButton (since the new PushButton will have a different name than the original). Classes store the code once and refer to the object (like the PushButton) generically so that the same code can be reused any number of times without modification. If you create a class based on the PushButton control and then add your code to that class, any usage (instances) of that custom class will have that code.
- Smaller Projects and Applications: Because classes allow you to store code once and use it over and over in a project, your project and the resulting application is smaller in size and may require less memory.
- Easier Code Maintenance: Less code means less maintenance. If you have basically the same code copied in several places of your application, you have to keep that in mind when you make changes or fix bugs. By storing one copy of the code, when you need to make changes, you'll spend less time tracking down all those places in your project where you are using the same code. Changes to the code in a class are automatically used anywhere where the class is used. Easier Debugging The less code you have, the less code there is to debug.
- More Control: Classes give you more control than you can get by simply adding code to the event handlers of a control in a window. You can use classes to create custom controls. And with classes, you have the option to create versions that don’t allow access to the source code of the class, allowing you to create classes you can share or sell to others.
Before you can use a class in your project, it is important to understand the distinction between these three concepts: the class itself, the instance of the class and the reference to the class.
- The Class: Think of the class as a template for a container of information (code and data), much like a module. And like a module, each class exists in your project only once. But unlike a module, a class can have multiple instances that each contain different data.
- The Reference: Classes provide better code reuse because of a concept called instances. Unlike a module, which exists only once in your application, a class can have multiple instances. Each instance (also called an object) is a separate and independent copy of the class and all its methods and properties.
Xojo has many built-in classes for user interface controls such as PushButton, WebButton, iOSButton, Label, WebLabel, iOSLabel, TextField, WebTextField, iOSTextField, ListBox, WebListBox and iOSTable to name just a few.
By themselves, control classes are not all that useful; they are just abstract templates. But each time you add a control class to a layout (such as a window, web page or view) you get an instance of the class. Because each button is a separate instance, this is what allows you to have multiple buttons on a window, with each button being completely independent of each other with its own settings and property values.
This is an example of a Vehicle class that will be used in later examples:
Class Vehicle Property Brand As String Property Model As String End Class
These instances are what you interact with when writing code on the window and is what the user interacts with when they use your application.
For example, when you drag a TextArea from the Library to a Window, you create a usable instance of the TextArea on the Window. The new instance has all the properties and methods that were built into the TextArea class. You get all that for free — styled text, multiple lines, scroll bars, and all the rest of it. You customize the particular instance of the TextArea by modifying the values of the instance’s properties.
When you add a control to a layout, the Layout Editor creates the reference for you automatically (it is the name of the control).
However, when writing code you create instances of classes using the New keyword. For example, this create a new instance of a Vehicle class that is in your project:
Dim car As New Vehicle
A reference is a variable or property that refers to an instance of a class. In the above code example, the car variable is a reference to an instance of the Vehicle class.
In your code you interact with properties and methods of the class using dot notation like this:
Dim car As New Vehicle car.Brand = "Ford" car.Model = "Focus"
Here the Brand and Model were defined as properties of the Vehicle class and they are given values for the specific instance. Having an instance is important! If you try to access a property or method of a class without first having an instance, you will get a NilObjectException likely causing your app to quit. This is is one of the most common programming errors that people make and is typically caused by forgetting the New keyword. For example, this code might look OK at first glance:
Dim car As Vehicle car.Brand = "Ford" car.Model = "Focus"
But the 2nd line will result in a NilObjectException when you run it because car is not actually an instance. It is just a variable that is declared to eventually contain a Vehicle instance. But since an instance was not created, it gets the default value of Nil, which means it is empty or undefined.
If you are not sure if a variable contains an instance, you can check it before you use it:
If car <> Nil Then car.Brand = "Ford" car.Model = "Focus" End If
When the variable is not Nil, then it has a valid reference. And since it is a reference, it has important considerations when assigning the variable to another variable: When you do an assignment from one reference variable to another, the second variable points to the same reference as the first variable.
This means the second variable refers to the same instance of the class as the first variable and is not a copy of it. So if you change a property of the class with either variable, then the property is changed for both. An example might help:
Dim car As New Vehicle car.Brand = "Ford" car.Model = "Focus" Dim truck As Vehicle truck = car // truck.Model is now "Focus" car.Model = "Mustang" // truck.Model is now also "Mustang" truck.Model = "F-150" // car.Model is now also "F-150"
In this diagram you can see that the variables for both car and truck point to the same instance of Vehicle. So changing either one effectively changes both.
If you want to create a copy of a class, you need to instead create a new instance (using the New keyword) and then copy over its individual properties as shown below:
Dim car As New Vehicle car.Brand = "Ford" car.Model = "Focus" Dim truck As New Vehicle truck.Brand = car.Brand trunk.Model = car.Model // truck.Model is now also "Focus" truck.Model = "F-150" // car.Model remains "Focus"
When you do it this way, you get two separate instances. Changes to one do not affect the other as you can see in these diagrams:
In Xojo, adding a class to a project is easy. To add a new class, click the Insert button on the toolbar and choose Class or select Class from the Insert menu. This adds a new class to the Navigator with the default name (Class1 for the first class).
Use the Inspector to change the name of the class. Like modules, classes primarily contain properties and methods. But they can also contain many other thing such as constants, enumerations, events and structures.
Properties are variables that belong to an entire class instance rather than just a single method. To add a property to a class, use the Add button on the Code Editor toolbar, Insert ↠ Property from the menu, the contextual menu or the keyboard shortcut (Option-Command-P on macOS or Ctrl+Shift+P on Windows and Linux). You can set the property name, type, default value and scope using the Inspector.
To quickly create a property, you can enter both its name and type on one line in the Name field like this: PropertyName As DataType. When you leave the field, the type will be set in the Type field.
Properties added in this manner are sometimes called Instance Properties because they can only be used with an instance of the class. You can also add properties that can be accessed through the class itself without using an instance. These are called Shared Properties.
A shared property (sometimes called a Class Property) is like a “regular” property, except it belongs to the class, not an instance of the class. A shared property is global and can be accessed from anywhere its scope allows. In many ways, it works like a module property.
It is important to understand that if you change the value of a shared property, the change is available to every usage of the shared property.
Generally speaking, shared properties are an advanced feature that you only need in special cases. For example, if you are using an instance of a class to keep track of items (e.g., persons, merchandise, sales transactions, and so forth) you can use a shared property as a counter. Each time you create or destroy an instance of the class, you can increment the value of the shared property in its constructor and decrement it in its destructor. (For information about constructors and destructors, see the section Constructors and Destructors.) When you access it, it gives you the current number of instances of the class.
To add a method to a class, use the Add button on the Code Editor toolbar, Insert ↠ Method from the menu, the contextual
menu or the keyboard shortcut (Option-Command-M on macOS or Ctrl+Shift+M on Windows and Linux). You can set the method name, parameters, return type and scope using the Inspector.
When typing the method name, the field will autocomplete with the names of any methods on its super classes.
Methods added in this manner are called Instance Methods because they can only be used with an instance of the class.
You can also add methods that can be accessed through the class itself. These are called Shared Methods.
A shared method (sometimes called a Class Method) is like a normal method, except it belongs to the class, not an instance of the class. A shared method is global and can be called from anywhere its scope allows. In many ways, it works like a module method.
Shared Methods do not know about an instance so its code can only access other shared methods or shared properties of the class.
Generally speaking, shared methods are an advanced feature that you only need in special cases. A common usage of shared methods is to create an instance (rather than relying on a Constructor).
Learn more about Xojo, the fast way to make apps for Windows, Mac, Linux, iOS and the web.