Introduction
In the previous lessons, we discussed in detail how to define classes and how to use objects created from these classes. In this lesson, we will learn how to create and use subclasses. A subclass inherits properties and methods from a parent class, called the superclass. Using some small examples, we will illustrate the usefulness of subclasses in object-oriented programming (OOP).
How to create a subclass?
For the class DesktopTextField , many properties, methods and events are already available by default. However, it can sometimes be very useful to add new methods to this class. Since it is not possible to add new methods to existing Xojo classes, we have to create a new subclass.
A subclass can be created in a simple way:

- Insert a new Class to your project (MainMenuBar – Insert – Class or via
button in toolbar);
- Name the new class (e.g. MyTextField) in the Inspector;
- Select the superclass (e.g. DesktopTextField)in the Inspector.
MyTextField is now a subclass from the superclass DesktopTextField. This means that an instance of MyTextField can be added to a window. MyTextField inherits all properties (e.g. Text) , methods (e.g. AddText) and events (e.g. TextChanged) from the superclass DesktopTextField.

Now you can drag and drop MyTextField from the navigator onto a Window. The default name of the object (new instance of MyTextField) will be MyTextField1, but can be changed. To keep the example simple, I kept the default name.
How to add methods to a subclass?

Now you can add new methods to the subclass named MyTextField. Four new methods were added in the example (ToCurrency, ToLowerCase, ToTitleCase, ToUpperCase).
Our discussion will be limited to the methods ToTitleCase and ToCurrency.
ToTitleCase
//ToTitleCase As String
Var t As String = Self.Text.Titlecase
Return t
This method is very simple. The Text property of MyTextField (denoted by the keyword Self) is converted by the String method TitleCase and assigned to the localString variable t. The converted string is then returned to the calling method.
In the MyTextField1 object, the new method can now be called via the TextChanged event:
//TextChanged event
Me.Text = Me.ToTitleCase
Now if you type the name “john de long” into MyTextField1 the name is automatically converted to “John De Long”.
ToCurrency
A monetary amount entered as text in MyTextField1 can easily be converted to a Currency data type via the method ToCurrency .
The ToCurrency method looks as follows:
//ToCurrency As Currency
Var v As Currency
Try
v = Currency.FromString(Self.Text, Locale.Current)
Catch error As RuntimeException
MessageBox("Error "+error.Message)
End Try
Return v
The FromString method is used to convert the value of the Text property of MyTextField into a Currency value. The parameter Locale.Current takes into account the local representation of money amounts (meaning of comma and period).
If the conversion fails a RunTimeException is raised. This error condition is caught by the Try..Catch..End Try construction. The converted value v is returned to the calling method.
An empty Currency value doesn't exist. The above code will return 0 if the conversion fails!
In the MyTextField1 object, the new method can be called via the KeyDown event:
//KeyDown(key As String) As Boolean
If key = Chr(3) Or key = Chr(13) Then
Var amount As Currency = Me.ToCurrency
MessageBox(Str(amount))
End If
Return False
The KeyDown event waits until End-Of-Text (ETX) (Chr(3)) is reached or Carriage Return (Chr(13)) is pressed. The ToCurrency method converts the Text of TextField1 into the Currency value named amount. In Europe the Text value €1.234,55 entered in MyTextField1 is converted to 1234.56. This value can now be used to perform calculations.
The Return statement returns False . Returning False means the key reaches the control. Returning True means the key is intercepted.
How to add properties to a subclass?
Properties can be added to a subclass in the usual way. For example, you can add the CurrencyValue property (type Currency – scope Private) to store the currency amount calculated from the Text property.
In this case, modify the ToCurrency method as follows:
//ToCurrency As Currency
Try
CurrencyValue = Currency.FromString(Self.Text, Locale.Current)
Catch error As RuntimeException
MessageBox("Error "+error.Message)
End Try
Return CurrencyValue
In the following paragraphs, I use a more practical example to illustrate adding events to a subclass.
How to add events to a (sub)class?

For the following example, I have two ‘special’ bank accounts: a retirement account (RetirementAccount) and a savings account (SavingsAccount). Both accounts are slightly different: for a retirement account, each deposit is limited to 1000.0 (MaximumAmount); for a savings account, on the other hand, the total account balance is limited to 5000.0 (MaximumBalance).

To solve this problem and illustrate the use of events, I created the class Account and two subclasses LimitAmountAccount and LimitBalanceAccount.
REMARK
There are several possible solutions to this problem. This solution was chosen to best illustrate the use of events.
Account
The class Account has a method named Deposit(scope Protected):
//Deposit(amount As Double)
AccountBalance = AccountBalance + amount
The class Account also has a property AccountBalance (Type Double – Scope Protected).
Protected means that the property or method can be used in the class itself and by its subclasses.
LimitAmountAccount
LimitAmountAccount is a subclass of Account: Account is the superclass (Super Account).
Because a special rule applies to this subclass (the deposited amount cannot exceed 1000.00), a special method Deposit was created for this subclass. The following method has been added:
//Deposit(amount As Double)
// Calling the overridden superclass method.
Super.Deposit(amount)
If amount > 1000.0 Then
RaiseEvent MaximumAmount
AccountBalance = AccountBalance - amount
End If
MessageBox(Str(AccountBalance))
Super.Deposit(amount)
The first statement (Super.Deposit(amount) ) is not difficult to understand: execute the Deposit method from the superclass (Account). In this case, the property AccountBalance is first incremented by the inserted value (amount). This statement is automatically added by Xojo if you refer to an existing method of the superclass (you want to override the existing method).
RaiseEvent MaximumAmount
The RaiseEvent MaximumAmount statement refers to an event named MaximumAmount.

The use of events is easy to understand if you think of an event as a special method called when a particular action is performed. An event (the ‘special’ method) must be defined in an Event Definition.
An Event Definition can be added by selecting the class and selecting the menu option Event Definition from the Insert menu.

Just as you define an ordinary method, for events you must also specify the name of the event, optional parameters and an optional return type. No further information is required.
An Event Definition needs only an Event Name, optional Parameters and an optional Return Type. No code is added in the coding pane.
The MaximumAmount event is called by the statement RaiseEvent MaximumAmount if the deposit in an account of the LimitAmountAccount subclass exceeds 1000.00. In this case, the account balance is also corrected back (the superclass already added the deposited amount) with the instruction AccountBalance = AccountBalance – amount.
How to use the new event?
Drag a class to the window
A (sub)class is just a template to define real objects. To use our new construction we have to create an object. A quick way to do this is to drag the class LimitAmountAccount into the window and define the Name (RetirementAccount), the Superclass (LimitAmountAccount) and the Scope (Private).

The object RetirementAccount knows one event (MaximumAmount). The Event Handler (what must be done if the deposit is greater than 1000.00?) can be added to the RetirementAccount. The following screenshot shows the way how the Event Handler is made available.

In this case, we chose to provide only an error message (“Amount > 1000.00!”) to indicate that this deposit will not be accepted. This piece of code can be added to the Event Handler:
//MaximumAmount
MessageBox("Amount > 1000.00!")
The same process can be used to create a new MaximumBalance event for the LimitBalanceAccount subclass.
The Deposit method for the LimitBalanceAccount subclass will be:
//Deposit(amount As Double)
// Calling the overridden superclass method.
Super.Deposit(amount)
If AccountBalance > 5000.00 Then
RaiseEvent MaximumBalance
AccountBalance = AccountBalance - amount
End If
MessageBox(Str(AccountBalance))
An Event Definition must be added to the subclass for the new Event MaximumBalance (Name MaximumBalance, no parameters, no Return).
A new object can be added by dragging the LimitBalanceAccountsubclass onto the Window. The new object is named SavingsAccount, Super is LimitBalanceAccount and Scope is Private.
The code for the Event Handler MaximumBalance could be:
//MaximumBalance
MessageBox("Balance Limit 5000.00!")
Create your class at runtime
In the previous lesson, we created the accounts at runtime with the statements RetirementAccount = New LimitAmountAccount and SavingsAccount = New LimitBalanceAccount. RetirementAccount and SavingsAccount were two properties defined in AccountWindow.
//Opening
RetirementAccount = New LimitAmountAccount
AddHandler RetirementAccount.MaximumAmount, AddressOf MaxAmountMethod
SavingsAccount = New LimitBalanceAccount
AddHandler SavingsAccount.MaximumBalance, AddressOf MaxBalanceMethod
We have now placed the above piece of code in the Opening event of AccountWindow. The two accounts are created at runtime. Because these objects are created at runtime, it is not yet possible to handle the MaximumAmount and MaximumBalance events . AddHandler associates an event with a method that must be executed when the event occurs.
The following syntax is used:
AddHandler eventName, delegateMethod
A delegateMethod is a pointer to a named method. AddressOf gets the address of the named method . This is the code of the referenced methods:
//MaxAmountMethod(sender As LimitAmountAccount)
MessageBox("Amount > 1000!")
//MaxBalanceMethod(sender As LimitBalanceAccount)
MessageBox("Balance > 5000!")
An additional parameter (sender As LimitAmountAccountin MaxAmountMethod , sender As LimitBalanceAccountin MaxBalanceMethod) is required for the methods that must be executed when the events occur. The first parameter of the referenced methods must always be of the type of the original object.
The first parameter of the method must always be of the type of the original object.
If you use Addhandler, you should always remove the handler when it is no longer needed. The handlers are removed in the Closing event of AccountWindow:
//Closing
RemoveHandler RetirementAccount.MaximumAmount, AddressOf MaxAmountMethod
RemoveHandler SavingsAccount.MaximumBalance, AddressOf MaxBalanceMethod