Xbasic Class Syntax
The syntax in this article describes Xbasic classes in Backus-Naur Form (BNF).
Keywords are in UPPERCASE and bolded.
Substitutable values (rules) are in angle brackets "<>". The rule for replacement is listed below.
Rules are expressed as <rule> : option | option | option; where the vertical bar "|" means "OR".
Values in square brackets "" are optional.
Underlined elements are the default for optional items.
The symbol "*" means that the element that precedes it can occur zero or more times. For simplicity sake, we have omitted commas in argument lists.
DEFINE CLASS [ GLOBAL | SHARED | LOCAL | SYSTEM ] <name> [ INHERITS <classname> ] <classelement>* END CLASS <classelement> : <constructor> | <dimStatement> | <functionStatement> | <constantStatement> <constructor> : FUNCTION [<simpleaccess>] <classname> (<functionargument>) function body END FUNCTION
- A class name may include a namespace prefix separated from the name by two colons (::).
- A namespace may have multiple parts separated by periods.
- A constructor function has the same name as the class.
- There can be multiple constructors per class. The constructor that executes depends on the arguments provided when the class is created. The new keyword is used to invoke a specific constructor.
- A constructor may have limited access to control how a class is created from outside.
<destructor>: FUNCTION ~<classname> ( ) function body END FUNCTION
- A destructor has the same name as the class with the tilde "~" character preceding it.
- There can be only one destructor per class.
- All destructors are public and virtual.
<dimStatement> : DIM [ <simpleaccess> | <mixedaccess> ] [ STATIC | VIRTUAL ] <name> [<arraydefinition>] AS <typename> [= <expression>] <functionStatement> : FUNCTION [<simpleaccess>] [ STATIC | VIRTUAL ] <name> AS <typename> ](<functionargument>) function body END FUNCTION <constantStatement> : CONSTANT [<simpleaccess>] <name> = <literal value>
<simpleaccess> : PUBLIC | PROTECTED | PRIVATE <mixedaccess> : <simpleaccess> READ | <simpleaccess> WRITE | <simpleaccess> READ <simpleaccess> WRITE <functionargument> : [ BYREF | BYVAL ] [ OPTIONAL | PARAMS ] AS <typename> [= <expression>]
- OPTIONAL indicates that the parameter may be omitted.
- The effect is the same as overloading the function.
- At run time, the initialization expression is executed if the argument is missing.
PARAMS can be used at most once in an argument list.
- It must be used on the last argument in the overload.
- At run time, all parameters in this position and those that follow must either match or be inherited from the type specified.
- The interpreter converts the arguments into an array of the same type as the declared type of the arguments collection.
The name of the class being defined
The valid Xbasic syntax for defining an array
A valid single letter type or class name
A valid Xbasic identifier
A valid Xbasic literal value (the type is implied)
A valid Xbasic expression (constant, new operator, and so on)
In the example below, note that the member variable InstanceCount is static. That means there is only one InstanceCount, no matter how many copies of TestClass have been DIMmed. On the other hand, each instance of TestClass has its own copy of the member variable Data.
Also note that the member method TestClass() is the constructor for class TestClass. Therefore it is called immediately after an instance of TestClass is DIMmed. Similarly, the member method ~TestClass() is the destructor for class TestClass. Therefore it is called immediately before an instance of TestClass is destroyed.
DEFINE CLASS TestClass dim read protected write Name as C dim Data as A dim read protected write static InstanceCount as N FUNCTION TestClass() Initialize() END FUNCTION FUNCTION ~TestClass() InstanceCount = InstanceCount - 1 END FUNCTION FUNCTION protected Initialize as V() Data = "" InstanceCount = InstanceCount + 1 END FUNCTION FUNCTION [static] DefaultDataType as C () DefaultDataType = "C" END FUNCTION FUNCTION AddToData as V ( PARAMS NewValue as C) for i = 1 to NewValue.Size() *concat(Data, NewValue(i)) next END FUNCTION FUNCTION AddToData as V ( PARAMS NewValue as N) for i = 1 to NewValue.Size() Data = Data + NewValue(i) next END FUNCTION FUNCTION Clear as V () Initialize() END FUNCTION END CLASS
How does this class keep track of its instance count?
How do the two AddToData overloads work?
There are at least two potential bugs in the class above. Can you find them?