Skip to content

Creating a Number Class

In this tutorial I will show you how to create a Number class that can tell you when its value has been actually set, along with other methods to manage how it is used while demonstrating some common object-oriented techniques and features such as operator overloading. You’ll be able to create a Number from an Integer, Double or String.

The Basics of the Number Class

Let’s start with the bare bones of this Number class. Add a new Class to a Xojo project and name it Number in the Inspector Panel.

The value of the Number class is going to be backed by a primitive double property. So add a new Property to the Number class and use the Inspector Panel with the following values:

  • Name: Value
  • Type: Double
  • Scope: Protected

We also want to know when a value is set to any of the Number instances, so go ahead and add a new Property to the Class using the following values in the Inspector Panel:

  • Name: IsSet
  • Type: Boolean
  • Scope: Protected

And of course we want to have the ability to enable or disable any Number instance, so its assigned value may or may not be taken into account when used in any mathematical operation, for example. Add the third of the properties required by our Number class:

  • Name: Enabled
  • Type: Boolean
  • Scope: Public

The next step is to add some constructor Methods to our class, so we can create new instances of it covering several common cases:

  • Creating a new instance with no value provided: IsSet property will be set to False, and the Enabled property will be set to True.
  • Creating a new instance with the Integer/Double provided: IsSet property will be set to True, and the Enabled property will be set to True.
  • Creating a new instance with the numeric value from the provided String: IsSet property will be set to True and the Enabled property will be set to True too.

The default constructor for the class will be the one with no parameters. So add a new method to the Number class using the following values in the Inspector Panel:

  • Method Name: Constructor
  • Scope: Public

And type the following line of code in the associated Code Editor:

Self.Enabled = True

Add a second method to the class and use the following values in the Inspector Panel (this constructor will create a new instance from the received Integer/Double value):

  • Method Name: Constructor
  • Parameters: value As Double
  • Scope: Public

And type the following lines of code in the associated Code Editor:

Self.Constructor
Self.Value = value
Self.IsSet = True

Let’s add the third constructor, the one taking a String as the parameter. Add a third method to the class using the following values in the Inspector Panel:

  • Method Name: Constructor
  • Parameters: value As String
  • Scope: Public

And type the following lines of code in the associated Code Editor:

Self.Constructor

Self.Value = Double.FromString(value, Locale.Raw)
Self.IsSet = True

But, wait! Wouldn’t it be great if we could create new Number instances from another Number instance received as the parameter? Of course it would! So add a new Method again using the following values in the Inspector Panel:

  • Method Name: Constructor
  • Parameters: value As Number
  • Scope: Public

And type the following lines of code in the associated Code Editor:

Self.Constructor

If value <> Nil and value.IsSet And value.Enabled Then
  Self.Value = value.Value
  Self.IsSet = True
End If

By now our class has four special methods, all of them with the same name: Constructor. If defined in any of your classes, this is the method that will be called/executed every time your code uses the New keyword in combination with the class data type. For example:

Var n As New Number // This calls the by default Constructor.
Var i As New Number(10) // This calls the Constructor taking an Integer/Double as the parameter.
Var s As New Number("120.20") // This calls the Constructor taking a String as the parameter.
Var objNumber As New Number(n) // This calls the Constructor taking a Number instance as the parameter.

When several methods are added to a class using the same method name but with different number of arguments or arguments data types (or returned values), that is called Method Overloading and you will find it in any object-oriented programming language. So our constructor method is overloaded to cover all the expected cases.

As you see, there is nothing fancy in the previous examples. I mean, creating a new instance from the received value in the constructor method is ok, but it would be even better and more simple if we could do something like:

Var i As Number = 10
Var s As Number = "120.20"
Var objNumber = n

Overloading the Assignment Operator

The good news is that we can do that! The Xojo programming language has the ability to overload operators too, just like we did with the constructor method! And when it is about to overload the assignment operator we implement the Operator_Convert method. This one will be called every time our class receives a value from another data type or needs to convert itself to the expected data type; for example:

Var i As Number = 10 // 10 Integer value needs to be converted to a Number instance.
Var intValue As Integer = i // The variable "i" (Number data type) needs to be converted to an Integer data type.

The most important thing to remember is that when Operator_Convert gets into play, the class Constructor is never called! So the code in the Operator_Convert method implementation needs to take care of properly initialising the instance as you expect.

So let’s start implementing the Operator_Convert that will be called every time a Number instance needs to be converted to an Integer or Double value.

Add a new method to the Number class using the following values:

  • Method Name: Operator_Convert
  • Return Type: Double
  • Scope: Public

And type the following line of code in the associated Code Editor:

Return If(Self.Enabled, Self.Value, 0)

Add a second Operator_Convert method, this time change the returned value to a String so our Number instances internal values can be easily assigned to a String variable (or used in other operations with Strings) like this:

Var i As Number = 10
Var s As String = i

Use the following values in the associated Inspector Panel and type the line of code in the associated Code Editor:

  • Method Name: Operator_Convert
  • Return Type: String
  • Scope: Public
Return If(Self.Enabled, Self.Value.ToString(Locale.Raw), "")

We need to overload the Operator_Convert method two more times so it can handle the assignment operation when the received value is at the right of the equal operator instead of the left.

Use the following values in the Inspector Panel for every one of the new two overloaded methods (typing the line(s) of code following each of these):

  • Method Name: Operator_Convert
  • Parameters: value As Double
  • Scope: Public
Self.Enabled = True
Self.Value = value
Self.IsSet = True
  • Method Name: Operator_Convert
  • Parameters: value As String
  • Scope: Public
Self.Enabled = True
Self.Value = Double.FromString(value, locale.Raw)
Self.IsSet = True

Overloading the Add Operator

Assigning values to Number variables or properties or Number instances to Integer / Double or String variables and properties is fine, but not so useful now. So the next step is adding Number instances with another Number instances, Integer / Double data types and also even with all the values from an array. To do this we need to overload the “+” (Add) operator implementing the Operator_Add method in the Number class.

This will allow us to write code like this:

Var n2 As Number = i + 10

Here the “10” value is first converted to a Number instance that is going to be added to the “i” Number instance and then assigned to the “n2” variable.

Var n3 As Integer = i + 10

Here the “10” value is first converted to a Number instance that is added to the “i” number instance and, then, the result converted to an integer value assigned to the “n3” variable.

So we need to implement the Operator_Add taking a Number parameter and returning also a Number data type.

Add a new method to the Number class using the following values in the Inspector Panel, and typing the lines of code following them in the associated Inspector Panel:

  • Method Name: Operator_Add
  • Parameters: Value As Number
  • Return Type: Number
  • Scope: Public
If value <> Nil Then
  Var no As New Number(If(Self.Enabled, Self.Value, 0) + value.Value)
  Return no
End If

That one works well when we have a Number instance to the left of the add operation, but not when the Number instance is to the right. For that scenarios we need to overload another method: Operator_AddRight.

Add another method to the Number class using the following values in the associated Inspector Panel:

  • Method Name: Operator_AddRight
  • Parameters: value As Double
  • Return Type: Double
  • Scope: Public

And type this line of code in the associated Code Editor:

Return If(Self.Enabled, Self.Value, 0) + value

Adding Number Instances to an Array of Integers

It would be also really helpful if we could add a Number to an array of integer values or even a Number instance to an array containing other array instances. For example, it would look like this in code:

Var arrayNumbers() As Number
Var arrayIntegers() As Integer

For z As Integer = 0 To 10
  arrayNumbers.Add(System.Random.InRange(10, 200))
  arrayIntegers.Add(System.Random.InRange(10, 200))
Next

Var z1 As Number = i + arrayNumbers
Var z3 As Integer = i + arrayIntegers

Of course this implies implementing new overloaded methods both for Convert_Add and Convert_AddRight. These are the implementations for overloading Convert_Add taking an Array of Doubles and also taking an Array of Number instances. I will let the Convert_AddRight implementation to you as exercice:

  • Method Name: Operator_AddRight
  • Parameters: value() As Integer
  • Return Type: Double
  • Scope: Public
Var sum As Double

For Each item As Double In values
  sum = sum + item
Next

Return sum + If(Self.Enabled, Self.Value, 0)
  • Method Name: Operator_AddRight
  • Parameters: value() As Number
  • Return Type: Number
  • Scope: Public
Var sum As Double

For Each item As Number In values
  If item <> Nil And item.Enabled Then sum = sum + item.Value
Next

Return sum + If(Self.Enabled, Self.Value, 0)

Unset Number Instances

The last step in this Number class is to implement the Method that will take care of Unset the instance; that is, kind of “reset” state where the value is still not defined.

Add a new Method to the Number class using the following values:

  • Method Name: Unset
  • Scope: Public

And adding the following lines of code to the associated Code Editor:

Self.IsSet = False
Self.Value = 0

Conclusion

As you see, method overloading is a powerful technique as we have done with the constructor method and also with the Operator_Convert, Operator_Add and Operator_AddRight methods. This Number class, with a little work, can be made to to cover other scenarios like the subtract, multiply or divide operations, among others. That wouldn’t be too difficult based on the implementations already exposed for the overloaded Operator_Add and Operator_AddRight methods. Download the Numbers class project.

Further Reading from the Xojo Blog Archives

Methods Overloading: Computed Properties, Setters and Getters

More on Object-Oriented Programming from the Xojo Blog and Xojo Documentation

Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón, Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at @XojoES or on the Xojo Forum.