Chapter 11

And now: OOP

We are entering the holy realm of the kingdom of OOP. But it will be a kind of tourist class ride. There will be no discussion about the history and purpose of this kingdom and no questioning of the many wise decisions made by the queens and kings of OOP. There will be mostly short explanations of each X# statement with a small example and, if appropriate, an C# example for a direct comparison.

Readers who already know VO know of course, that VO was a sophisticated OOP language from the beginning so neither X# nor C# offers anything completely new - with a few exceptions. One of them is generic classes (which are not so important in many projects).

The OOP syntax of X# is simpler and, from my modest perspective, a little more consistent and therefore easier to use than VO and also C#. Therefore, X# source code is (at least for me) better readable than its VO counterpart.

A closer look at Function Start()

Although in its simplest incarnation, an X# program only has to contain a single function, classes are no options. They are always present. Every X# application contains at least a single class definition.

Even the famous "Hello, World" program that only contains a single Start() function will be compiled into a class definition called "Functions" that contains a single static method Start. Still skeptical? I'll recommend the very good ILSpy to translate the IL code, generated by the compiler, in either C# or X# code (if the X# plugin is installed).

Alt ILSpy shows the reassembled IL code of the Hello,World programm

Fig 11.1: ILSpy 6.0 shows the reassembled IL code of the Hello, World program as X# source code

Defining classes

The definition of a class always starts with the Class statement followed by the class name and always ends with a End Class statement.

Although class definitions are usually part of a namespace, namespaces are always optional. Namespaces allow to structure of type definitions into logical groups. Visual Studio always defines a root namespace with the same name as the project itself. It's no problem to change that name.

Alt Visual Studio defines a default namespace for each project

Fig 11.2: Visual Studio defines a default namespace for each project

Namespaces are usually defined in code. A namespace definition begins with Begin Namespace and ends with End Namespace.

Begin Namespace Ns1

   Class C1

   End Class

End Namespace

Begin Namespace Ns2

   Class C2

   End Class

End Namespace

Function Start() As Void
   var oC1 := C1{}
   ? oC1:GetType():FullName

In X# there is no need to use the namespace for accessing (qualifying) the class definitions. But the namespace is part of the type name.

Example 11.1: (XS_Namespaces.prg) ** You will find the source code in the repository

Defining constructors

A class constructor in X# is defined with the Constructor statement. There is no need to end a constructor with an End Constructor or even a Return statement.

A class can have several constructors with different signatures (always distinguished by the number and the type of its parameters). Since X# has no overload keyword like Visual Basic, overloaded methods are just multiple methods inside a class with the same name but different signatures.

Since constructors, methods, etc. need no formal end statement, the following X# code is valid:

**Example 11.2: (XS_ClassDefinition.prg) **

// A simple class definition with an overloaded constructor and method
Begin Namespace NS1
  Class C1

    Constructor()

    Constructor(Count As Int)

  End Class

End Namespace

Function Start() As void
  var oC1 := C1{}
  ? oC1
  var oC2 := C1{100}
  ? oC2

Commonly, members of a single class have the same name. They have to differ in their signature though (the return type of a method does belong to the signature in X#).

Partial classes

A partial class is just a class definition split over several "locations" (usually different files). So it's the same class definition but the definition can be split over more than one class keyword. It's very convenient because a class definition with many members and/or lines of code does have to be part of a single class command.

All it needs is to add the Partial keyword to every class definition of the class.

X# is not Java, so the name of the prg file doesn't matter.

tip: Although it usually won't matter much, I recommend putting only one class definition in a file. If an enum is used by several classes, I would put the enum definition in the "first" class definition (whatever that means inside a specific project) and not in a separate file that would only contain that single enum definition.

**Example 11.3: (XS_PartialClass.prg) **

// A partial class definition

Partial Class App

  Static Method M1() As String
    Return "This is M1"

End Class

Partial Class App

  Static Method M2() As String
    Return "This is M2"

End Class

Function Start() As Void
 ? App.M1()
 ? App.M2()


NOTE: C# also supports partial methods. This feature is not available in X# and I don't see a big need for it. Partial methods in C# are for code that gets generated by a generator. When the partial method is not implemented, then the call to that partial method will be simply removed from the IL.


Anonymous classes

Anonymous classes are another kind of class that is mostly used as part of a LINQ query. Another term is anonymous types. The X# help file has a section on this topic so I will cover it only shortly.

Imagine needing an object for combining several values but it is not worth for formal class definition. This is a situation where an anonymous class is helpful.

It's just a class without an official name.

The syntax is simple and since the Class keyword is involved the syntax is a little better readable than in C#.

var value := Class { TimeStamp := DateTime.Now, Value := 0.1234 }
? value.toString()C#

There are many restrictions in comparison with a "real" class. Only read-only fields are allowed as members so anonymous classes are more or less a better way to return objects with custom properties from a LINQ queries like records would.

Although LINQ will be covered in a separate chapter, here is already a small example that uses an anonymous class.

**Example 11.4: (XS_AnonymousClass.prg) **

// Another example for an anonymous class

using System
using System.Linq

Function Start() As void
  var Months := From m in Enumerable.Range(1,12) Select Class { Month := DateTime{2022,m,1}.ToString("MMMM"),Days := DateTime.DaysInMonth(2022,m) }
  ForEach var m in Months
   ? m
  Next

Simple and hopefully "clean" too. But of course, there a simpler ways to achieve this result without these "modern ingredients".

Generic classes

The last cousin of Uncle OOP is the generic class (or better generic classes - and you don't need to know that C++ has a similar concept called templates). A generic class takes one or more type variables for its declaration. The name is usually T so if you have encountered a value as Tdeclaration and found it suspicious, now you have the explanation for this unusual type name.

This type of placeholder can be used for any constructor or member parameter to declare, that the parameter is of that type that is unknown at compile time.

In simpler terms: Since the type of a parameter or the return value of a method is based on a "variable" that gets a type value when the class is instantiated, generic classes offer a little extra flexibility.

I have never had use for generic classes in my projects, but there is one example that will persuade everybody immediately: A generic Swap() method. Although it's more an example of a generic method than of a generic class, it's really useful because it shows how to use a generic placeholder as part of a class and a method definition.

**Example 11.5: (XS_GenericClass.prg) **

// A simple generic class example

Class Swap<T>

   Method Swapit(op1 Ref T, op2 Ref T) As Void
     Local h := op1 As T
     op1 := op2
     op2 := h

End Class

Function Start() As Void
  var swap1 := Swap<Int>{}
  var v1 := 100
  var v2 := 200
  swap1:Swapit(v1, v2)
  ? i"v1={v1} v2={v2}"
  var swap2 := Swap<Double>{}
  var v3 := 12.345
  var v4 := 59.566
  swap2:Swapit(v3, v4)
  ? i"v3={v3} v4={v4}"
  // this won't work
  // swap1:Swapit(v3, v4)

The class uses the generic type placeholder T. When instantiating the class, T has to be replaced with a real type like Int or any other type.

Because a swap method has no return values, the little example also shows how to pass ref parameters in X#. A ref parameter is a parameter where the argument is passed by reference and not by value. All that is needed in X# is to use ref instead of as (which I think is a good syntax).

Nested classes

All the type definition structures like Classes and Structures can be nested. So, a class definition can contain another class definition. This section is included more for the sake of completeness. I would recommend not using it too much, if there is any need at all, because it violates the (from my perspective) important requirement for a "separation of concerns". Instead of embedding a class definition inside of another class definition, I would try to use a technique like "good, old dependency injection" to "inject" the extra functionality of the embedded class into the "main class". As Uncle Bob probably would say: "Keep your design as simple as possible". But this is another topic that is open for discussion.

Implementing members of a class

A class definition has to contain members otherwise the class definition would be pointless. There are several member types:

  • Fields
  • Properties
  • Methods
  • Enums
  • Events
Membertype Definition Where is it used for?
Fields A property without a getter/setter Private Variables
Property Contains a getter/setter To make instance data accessible outside the class
Method A regular method inside the class To make methods accessible outside the class
Enum A list of constant value Convenient for values that only have specific values
Event A general callback mechanism When a prefined callback should be called

Tab 11.1: The different member types a X# class definition can contain

From the member types listed in the table, only events are not used very often.

Reference instance members with Self

To reference an instance member inside the class definition, X# uses the keyword Self which I find more appropriate than the equivalent keyword this in C#. I know that some readers will disagree. Visual Basic uses Me which is a little amusing.

The only (small) problem in X# is that Self is optional unless a compiler option is set. This can lead to inconsistencies that do not improve readability.

The following mix between using Self and not using Self is allowed inside a class definition:

Class SuperVM
   Property NumberOfCores As Int32 Auto
   Property GBRam As Int32 Auto

   Constructor(NumCores As Int, Ram As Int32)
      NumberOfCores := NumCores
      Self:GBRam := Ram

   Method ToString() As String
     Return i"Cores: {NumberOfCores} Ram: {Self:GBRAM} GB"

End Class

This is not such a big problem because the property names are not identical to the parameter names.

If the constructor looks like this the compiler will issue a warning:

Constructor(NumberOfCores As Int, RamGB As Int32)
    NumberOfCores := NumberOfCores
    GBRam := RamGB

You will avoid this warning by using Self for both assignments.


NOTE: There is a compiler switch /enforceself which should, as the name implies, enforce the use of Self, but it seems to have no effect (at least on my PC with Cahors 2.14).


Example 11.6: (XS_SelfInClass1.prg) ** You will find the source code in the repository

Example 11.7: (XS_SelfInClass2.prg) ** You will find the source code in the repository

Instance members and static members

A class definition can only provide static members to its users. Static members are declared with the Static keyword and are accessed with the . operator.

The DateTime class of the .Net runtime is a good example because it offers a few useful static members like DaysInMonth which returns the number of days for a given month in a given year.

// Getting the days in a month
DateTime.DaysInMonth(2022, 2)

A nonstatic member of the DateTime class is AddDays() which adds (or subtracts) a given number of days to (from) a date. Another name for a nonstatic member is instance member because it is applied to the instance of a class.

// Getting the date of 90 days ahead from today
DateTime.Now:AddDays(90)

The example shows that instance members are accessed with a colon instead of a dot.

The constructor can also be static. It will be called when a static member of the class is used the first time.

**Example 11.8: (XS_StaticConstructor.prg) **

// Example of a class with a static constructor

Public Class StaticConstructor

    Static Constructor()
        Console.WriteLine("*** This is the static constructor ***")

    Constructor()
        Console.WriteLine("*** This is the instance constructor ***")

    Static Property Id As Int Auto

End Class

Function Start() as Void
  // Calls the static constructor
  StaticConstructor.Id := 1234
  ? StaticConstructor.Id

Handling events

Events provide some kind of callback mechanism so that anytime "something happens" a predefined "event handler" (method or function) will be called.

Events are another kind of member a class definition can have.

Events are mostly used inside a GUI application so that common actions like a mouse click, a press of a key, and many more can be handled by custom code.

Any more technical explanation needed?

From time to time I am just too lazy to write a definition I have probably written and explained a "100 times" in the last 30 years or so. Fortunately, the definition in the Microsoft docs is really good. So here it is:

An event is a message sent by an object to signal the occurrence of an action. The action can be caused by user interaction, such as a button click, or it can result from some other program logic, such as changing a property's value.

The object that raises the event is called the event sender.

The event sender doesn't know which object or method will receive (handle) the events it raises.

The event is typically a member of the event sender; for example, the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that implements the INotifyPropertyChanged interface.

Since an event can have multiple event handlers assigned to it, an event handler is always added with the += operator (and could be removed with the -= operator).

There is even an optional add/remove method inside an event definition to execute code when an event handler is hooked and unhooked. In case of a timer event, the timer would stop when no event handler had been registered for the event so that the timer wastes no CPU cycles. The X# help contains a very good example. Please have a look.

There are at least three different ways in X# to handle an event with an appropriate event handler:

  1. The classical event handler as a method or function
  2. By using the Delegate keyword and an anonymous method
  3. By using a lambda

Although event handling is nearly exclusively used as part of a GUI application, I will demonstrate the basic event handling techniques inside a simple console application that does not have an official class definition. And of course, I will use the famous Timer class of System.Timers namespace that is part of System.dll.

One reason for not using the Timer class inside a WinForms or WPF application is the fact that the event handler of the Timer class always runs on a different thread which takes a little extra step if the event handler should access the GUI. More on this in Chapter 13.

Option A - a method as an event handler

The following example shows how to use our regular method definition as an event handler. After start, the message "elapsed" is printed in the console window every second.

**Example 11.9: (XS_TimerExample1.prg) **

// Timer-Events - option A
using System
using System.Timers

function ElapsedHandler(Sender As Object, e As EventArgs) as Void
    ? "Elapsed..."

Function Start() As Void
   var tmr := Timer{}
   tmr:Interval := 1000
   tmr:elapsed += ElapsedEventHandler{ElapsedHandler}
   tmr:Start()
   Console.WriteLine("Press any key please...")
   Console.ReadLine()

Option B - a delegate as an event handler

The following example shows how to use a delegate as an event handler. It's the same example as the last one but with a different kind of event handler.

**Example 11.10: (XS_TimerExample2.prg) **

// Timer-Events - option B
using System
using System.Timers

Function Start() As Void
   var tmr := Timer{}
   tmr:Interval := 1000
   tmr:elapsed += Delegate(Sender As Object, e As ElapsedEventArgs) {
    ? "Elapsed..."
   }
   tmr:Start()
   Console.WriteLine("Press any key please...")
   Console.ReadLine()

Option C - a lambda as an event handler

The following example shows how to use a lambda expression as an event handler.

**Example 11.11: (XS_TimerExample3.prg) **

// Timer-Events - option C

using System
using System.Timers

Function Start() As Void
   var tmr := Timer{}
   tmr:Interval := 1000
   tmr:elapsed += {Sender, e => 
    ? "Elapsed..."
   }
   tmr:Start()
   Console.WriteLine("Press any key please...")
   Console.ReadLine()


NOTE: The lambda as an event handler in this example is a so-called "Multi Line Lamda" (MLL). You have to be careful to not write any code after the => operator and continue to the next line. Also, the closing curly must be on a line of his own.


Making objects

Usually, a class is just a definition. To get objects, the class has to be instantiated. The X# designers came up with a syntax that I like better than the C# version. There is no new operator in X# instead a {} is following the type name.

Instantiating classes the X# way

The following example instantiates the StreamReader class.

Local sr := System.IO.StreamReader{"C:\Test123.dat"} As System.IO.StreamReader

Using the var keyword makes declaring a type for local variables unnecessary:

var sr := System.IO.StreamReader{"C:\Test123.dat"}

Although no type name is part of the declaration, sr is strongly typed of course. The compiler gets the type info from the assignment. But this only works with local variables.


NOTE: Robert asked me to mention that the syntax with the curly braces was not invented by us, but by the VO team.


Instantiating classes the C# way

Just for comparison, a small example shows how to instantiate a class in C#.

System.IO.StreamReader sr = new System.IO.StreamReader("C:\Test123.dat")

In both languages, everything gets simpler of course when the namespace has been declared through a using statement.

The following example instantiates a class without the namespace.

var sr := StreamReader{"C:\Test123.dat"}

Life in general and programming would be easier if there would always be a precise definition for a term. The terms object and instance are interchangeable most of the time. Some people argue, that objects means any instance of a class where instance refers to a specific instance.

But no one would hopefully argue that you can have an instance of an object.

Inside a class definition, the current instance is addressed by using Self (and not this like in C#).


NOTE: In the FoxPro dialect the This keyword is also supported.


Making instances using

It's recommended to create instances with Begin Using and End Using. This only works with classes that implement the IDispose interface. The benefit is, that neither an explicit close() nor a Dispose() call are necessary because both methods are called automatically.

**Example 11.12: (XS_BeginUsing.prg) **

// Example for Begin using - class has to implement IDisposable

Class C1 Implements IDisposable

   Method Dispose() As Void
     ? "Calling dispose..."


End Class

Function Start() As Void

   Begin Using var oC1 := C1{}
      ? "Inside Begin using..."
   End Using
   ? "End of function.."

If you start the application, the message "Calling dispose..." is automatically called when the object gets destroyed after End Using.

The regular way without Begin Using and End Using.

Local sr := StreamReader{"C:\Test1234.txt"} As StreamReader
? sr:ReadLine()
sr:Dispose()
sr:Close()

The more convenient way.

Begin Using var sr := StreamReader{"C:\Test1234.txt"}
? sr:ReadLine()
End Using

Begin Using and End Using are used often for accessing data readers when accessing a database. In many cases, Begin Using and End Using are nested.

A small drawback is that the variable is always local to the Begin Using block.

It's also possible to use a variable that is already in use in the class definition.

**Example 11.13: (XS_BeginUsingWithClassVariable.prg) **

// Begin Using with a class variable
using System
using System.IO

Class Test
   Private Sw As StreamWriter

   Method Save() As Void
      Begin Using Sw := StreamWriter{"Test.dat"}
        Sw:WriteLine("Hello, again!")
      End Using
      ? "*** File written ***"
      Return

End Class

Function Start() As Void
   var t1 := Test{}
   t1:Save()


NOTE: Its interesting to note that X# supports Using for variables that need to be disposed just like C# with version 8.0 and beyond. The variable will be automatically disposed of when it leaves its scope. You no longer need to use BEGIN USING .. END USING for this (an example will follow in a future version of this book).


Initializing properties when instancing an object

You may have heard rumors claiming that constructors are coming out of fashion. Can this be true? At least when a constructor just does initializing properties, they are not needed anymore because C# and X# also offer a simple alternative.

The simple alternative is to initialize the properties with the instancing of the object. As with the instancing itself, the X# requires an empty {} before the {} that contains the initializing values.

The following example shows how to initialize properties when instantiating a class in C#:

var o = City{Name="Esslingen", Inhabitants:90000}

The following example shows in comparison how to initialize properties when instantiating a class in X#:

var o := City{}{Name:="Esslingen", Inhabitants:=90000}

Example 11.14: (XS_InitProperties.prg) ** You will find the source code in the repository

The assignment order doesn't matter of course and not all properties of the class have to be assigned on this occasion. There is one restriction. The scope of the property has to be either Public or Internal.

This little feature is really handy because it makes the code shorter and better readable. Most C# developers have probably using it for many years.

This technique is also available for Lists and Dictionaries. More on this later in this chapter.

Visibility of class members

Each member of a class can have its visibility. It makes the member accessible from another class or not. The most restricting scope modifier is Private. A private member can only be accessed from inside the class definition. Since the default modifier is public, it looks like there would be no need to take the different modifiers into account.

Keyword Definition VO When is it used?
Public Visible from outside the class Export For members that should be available through the instance of the class (Default)
Private Visible only from inside the class Hidden For members that should not be available through the instance of the class
Protected Visible only inside class definitions that inherit from the definition class - -
Internal Visible from outside the class but not from outside the application. - -
Protected Internal Visible only inside class definitions that inherit from the definition class but not from outside the application. - -

Tab 11.2: X# keywords for declaring the visibility of a member

The following example shows a very simple class library that contains a class Misc that contains a single static method GetNumber. There a no scope modifiers needed.

**Example 11.15: (XS_ClassLib.prg) **

// Example for a class lib

Begin Namespace XLib

  Class Misc

     Static Method GetNumber(Max := 100 As Int) As Int
         Return Random{}:Next(1,Max)

  End Class

End Namespace

The next example shows a very simple console application that uses the class library. To compile it, use the /r compiler switch:

xsc .\XS_UseClassLib.prg /r:XS_ClassLib.dll

**Example 11.16: (XS_UseClassLib.prg) **

// Uses the XLib library

using XLib

Function Start() As Void
   var z := Misc.GetNumber()
   ?i"The magic number is {z}"

Defining enums

An enum (short for enumeration) is a type of the Common Type System (CTS) of the .Net runtime. An enum combines an arbitrary list of names. In X# each name is a constant with a given type or Int32 if no type is given.

The following examples define an enum CarColor that contains several constant (Int32) values.

**Example 11.17: (XS_EnumDefinition.prg) **

// The example for an enum definition

/// <summary>
/// Defines the possible colors for a car
/// </summary>
Enum CarColor
     Red
     Green
     Blue
     Yellow
     White
     Black
     Pink
End Enum

Function Start() As Void
   Local carColor1 := CarColor.Red As CarColor

   If carColor1 == CarColor.Red
     ? "*** The color is red ***"
   End if

It's important to understand that each name like Red or Blue is still an Int32 value and nothing else. Although it's possible that an enum explicitly inherits from another data type, this option is rarely used (if at all).

Now CarColor can be used as a regular data type.

Local carColor1 := CarColor.Red As CarColor
If carColor := CarColor.Red

End if

But since CarColor.Red is just an Int32 value, a direct comparison is valid as well:

If carColor := 0

End if

Although it's convenient to not have to assign values it's possible of course.

**Example 11.18: (XS_EnumWithInitValue.prg) **

// An enum with a discrete value for a member

/// <summary>
/// Defines the possible colors for a car
/// </summary>
Enum CarColor
    Red
    Green
    Blue
    Yellow
    White := 100
    Black
    Pink
End Enum

function Start() As Void
   Local carColor1 := carColor.White As CarColor
   ? carColor1

Red has the value 0, Green the value 1 etc. Since White has been assigned with the value 100, Black has the value 101, and Pink finally has the value 102.

The enum type offers several members for accessing the names and values of the enum.

ForEach var colName In Enum.GetNames(typeof(CarColor))
    ? colName
Next

ForEach var colVal In Enum.GetValues(typeof(CarColor))
    ? (int)colVal
Next

Personal note (might be boring): I still remember reading in the late 70s an article about the language Pascal in a computer magazine. A code example showed a loop where the loop variable ran from Monday to Sunday. I was so amazed that this was possible not knowing that the names were just constants.


So, I was delighted to find out that this is possible in X# too. There is one small caveat. For being able to use the "unqualified" enum names, the enum type has to be imported with the using static command (which I didn't know before someone suggested it on SO and mentioned that it's part of C# since version 6.0)'.

The following examples use unqualified enum names.

Ex

Alt Looping through an enum Fig 11.3: Looping through an enum


NOTE: There is a [Flags] attribute for enums. It allows you to combine several logical switches into one enum value. This is used a lot by system-level code, including the X# runtime.


Defining properties

A property can be defined in two different manners: Formal and a little cumbersome and in a modern syntax that fits a modern life style with avoids hard labor;)

The old way of VO with Access and Assign is also possible in X# but I would not recommend this syntax for a new project.

Ex

The "official" way of defining a property uses the Property keyword.

The formal definition first originates from the early days of OOP:

**Example 11.19: (XS_PropertyDefinition1.prg) **

// The formal definition of a class property

/// <summary>
/// Defines the possible colors for a car
/// </summary>
Enum CarColor
     Red
     Green
     Blue
     Yellow
     White
     Black
     Pink
End Enum

Class Car
    Private _Model As String
    Private _Color As CarColor

    Public Property Model As String
        Get
            Return _Model
        End Get
        Set
            Self:_Model := Value
        End Set
    End Property

    Public Method SetColor(Color As CarColor) As Void
       Self:_Color := Color

    Public Method ToString() As String
       Return i"Model: {Self:_Model} Color: {Self:_Color}"

End Class

Function Start() As Void
    var car1 := Car{}
    car1:Model := "Ford Escort"
    ? car1:Model

X# accepts a shorter version as an inliner:

Public Property Model As String Get _Model Set _Model := Value 

Just a note that either the "getter" or the "setter" can have a more restrictive visibility than the property itself but I won't cover that.

**Example 11.20: (XS_PropertyDefinition2.prg) **

// The modern way of defining a a class property

/// <summary>
/// Defines the possible colors for a car
/// </summary>
Enum CarColor
     Red
     Green
     Blue
     Yellow
     White
     Black
     Pink
End Enum

Class Car
    Private _CarColor As CarColor
    Private _Model As String
    Public Property CarColor As CarColor Get _CarColor Set _CarColor := Value
    Public Property Model As String Get _Model Set _Model := Value

    Public Method ToString() As String
       Return i"Model: {Self:_Model} Color: {Self:_CarColor}"

End Class

Function Start() As Void
  var car1 := Car{}
  car1:Model := "Ford Escort"
  ? car1:Model

In X# Value is just a placeholder for the value that will be assigned to the property.

As already mentioned, to access the current instance of the class inside the class definition X# uses the keyword Self and not this as in C#.

Since it would be insane to have to write a complete property definition with a getter and a setter for each property that does nothing but to set and return the value of another private variable there is a practical shortcut: the auto keyword.

Ex

Another option is, of course, to let Visual Studio do the coding by putting the cursor inside the private field definition and clicking on the light bulb, and choosing "Encapsulate field".

Alt Visual Studio offers encapsulating a field in a property definition Fig 11.4: Visual Studio offers to encapsulate a field in a property definition

The shortest definition of a property uses the Auto keyword. It instructs the compiler to generate an internal getter and setter. So these are real properties and not fields.

Public Class Car Inherit Vehicle
    Public Property Model As String Auto
    Public Property Color As CarColor Auto

It's no problem at all using the same property names inside a constructor as the parameter names. By using Self: the distinction will be clear between the parameter and the property. It compiles without Self: but then the compiler issues a warning and the assignment will be made to the same variable which is not what we want.

**Example 11.21: (XS_AutoProperties.prg) **

// A class definition with auto properties

Public Class Document
    Public Property Id As Int Auto
    Public Property Title As String Auto
    Public Property PubYear As Int Auto

    Constructor(Id As Int, Title As String)
       Self:Id := Id
       Self:Title := Title
       Self:PubYear := DateTime.Now:Year

    Method ToString() As String
      Return i"Id:{Self:Id} Title:{Self:Title} PubYear:{Self:PubYear}"
End Class

Function Start() As Void
  var d1 := Document{1, "C# no more"}
  ? d1:ToString()

Extension methods

An extension method is an interesting concept because it allows adding a method to type without having to extend the definition of that type. So the main advantage is that the extension method can be treated like a regular method of that type which makes calling the method more convenient.

My favorite example (and that of many other authors too) is adding a static Capitalize member to the string class to make it possible to write:

"Casino Royal".Capitalize()
Casino Royal

Without the extension method, it would be something like:

Capitalize("casino royal")

Extension methods are not so much about which programming style is better. This is only a side effect. They are one of the main ingredients of LINQ which I will cover in another chapter of this book.

Defining an extension method is done in X# nearly the same way as in C#. The main difference is that in X# you have to use Self instead of this. Besides that, the extension method is a static method in another class and the first parameter must be preceded by self. The type of this parameter is the type to which the method is added automatically by the compiler.

Extension methods are another example where the X# Visual Studio extensions are behind. Whereas in C# extension methods are like native methods part of the member list this is not the case with X# (yet).

**Example 11.22: (XS_ExtensionMethod.prg) **

// Example for an extension method

Class StringEx 

  Static Method Capitalize(self str As String) As String
    Local strRet := "" As String
    ForEach var w in str:split(c" ")
       strRet += w:Substring(0,1):ToUpper() + w:Substring(1) + " "
    Next
    Return strRet:Substring(0, strRet:Length - 1)

End Class

Function Start() As Void
  Local s1 := "casino royal total" As String
  ? s1:Capitalize()

Alt The extension method "feels" and behaves like a "real" method but it's not shown by intellisense Fig 11.5: The extension method "feels" and behaves like a "real" method

There is a second option for designating an extension method with the Extension attribute like so:

[Extension(String)];
Static Method Capitalize(str As String) As String

It works but also results in a compiler warning XS1112 that leaves no doubt about what the preferred choice should be.

Inheritance

A class inherits the member definitions of another class with the Inherit keyword.

You will find this line in any WinForms application:

Public Partial Class Form1 ;
       Inherit System.Windows.Forms.Form

I always wondered (many times) why the code generator did not simply write:

Public Partial Class Form1 Inherit Form

But please don't try to fix this in the designer of the form file;)

There a several terms for the class another class inherits from: base class and super class. In X# it's the superclass.

Calling the constructor of the base class

Whenever a class that is derived from a superclass is instantiated the superclass (and all the other superclasses in the inheritance chain as well) will be instantiated too.

This means that if the superclass does not explicitly contain a constructor without any arguments the constructor of the superclass has to be called inside the constructor of the derived class.

This is accomplished by calling Super() as the first statement inside the constructor with all the needed arguments.

**Example 11.23: (XS_CallSuper.prg) **

// Calling super() from an inherited class

Public Class Vehicle
    Public Property Id As String Auto
    Public Property Description As String Auto

    Constructor(Id As String, Description As String)
        Self:Id := Id
        Self:Description := Description
        Return

End Class

Public Class Car Inherit Vehicle
    Public Property Model As String Auto
    Public Property Color As String Auto

    Constructor(Id As String, Description As String, Model As String, Color As String)
        Super(Id, Description)

End Class

Function Start() As Void
    var c1 := Car{"qasc1", "The Nissan Qashqai", "1.3 DIG-T", "White"}
    ? c1


NOTE: To be compatible with VO, its possible that the SUPER() call is NOT the first line in the constructor.


Interfaces

An interface is a class definition that contains only the member definitions and absolutely no other statements.

The whole purpose of an interface is to be implemented in a class. It's a requirement that every member of the interface has to be implemented in the class.

During the beginning of the OOP area, 90% of all authors used animals for their examples. A dog class, for example, has to implement the IDoc interface that contains a bark() method.

The name of an interface does not have to start with an I of course. That was just a convention introduced with the invention of COM by Microsoft in the mid-90s. But it's really hard to not use an interface name that does not start with an I.

Then came cars. So here we go again.

An application uses classes to describe different kinds of vehicles like cars, trucks, buses, etc. Instead of using a vehicle superclass, all classes have to implement an IVehicle interface.

Most recent versions of X# do not offer a separate template for an interface, which might change shortly. Until then, we have to choose the class template.

**Example 11.24: (XS_IVehicle.prg) **

// An example for an Interface definition
// For compiling with xsc use /t:library

/// <summary>
/// The IVehicle interface
/// </summary>
Interface IVehicle
    Public Property Id As String Auto
    Public Property Description As String Auto
     Public Method Register(RegisterDate As DateTime) As Int
End Interface

Interfaces are defined with the Interface keyword and later implemented in a class with the Implements keyword. Similar to a class definition the interface definition contains properties, methods, and events but no fields.

The important difference to a class definition is the fact that an interface always contains only the definition of the method but no code at all. As soon as you would an assignment into a method definition you are on the wrong path (although the X# compiler won't complain')

The interface above contains three members: ID, Description, and Register().

It's a basic rule for all programming languages that an interface always has to be fully implemented with all its members.

So the following class definition won't compile:

Public Class Car3 Implements IVehicle

End Class

The X# Visual Studio Extension offers a helpful shortcut (that all other languages I know of provide too). If you click on the light bulb on the left a context menu opens that contains several entries:

  1. Generate default constructor
  2. Implement IVehicle
  3. Implement explicitly IVehicle

Both option 2 and 3 will implement the interface with all its members. When using the explicit version each member name will be preceded by the name of interface for a method and by the name of interface + ".EXPORT" for a property. I always choose option 2.

The resulting class now contains the implemented members:

Public Class Car3 Implements IVehicle

    #region Implement IVehicle

     Public Property Id As String Auto
     Public Property Description As String Auto
     Public Method Register(RegisterDate As DateTime) As Int
            Throw NotImplementedException{}

    #endregion
End Class

As with version 2.11 of the X# extension, the simple code generator contains several errors:

  1. Property is proceeded with Export which led to a compile error
  2. The Method keyword is missing

Alt Visual Studio makes implementing an interface in a class definition easy Fig 11.6: Visual Studio makes implementing an interface in a class definition easy

It's no problem of course that a class inherits and implements at the same time. In this case both Inherit and Implements is used:

class C1 Inherit S1 Implements ISpecial

The class C1 inherits from S1 and implements ISpecial.

The idea of interfaces is to make different classes "type compatible" without having to use a single superclass or several superclasses that inherit from the same super-super class.

This leads to Polymorphism (one of the four pillars of OOP besides abstraction, encapsulation, and inheritance). An example follows shortly.

There is a good overview of the four pillars of OOP: The 4 pillars of OOP

But probably all programming books and of course Wikipedia describe this topic very well too.

Since the implementation of the interface and its methods can be different in each class, interfaces are more flexible than inheritance for application development.

Interfaces as types

It might seem a little unusual at first that interfaces can used as a data type for generic lists for example.

Local vehicles := List<IVehicle>{} As List<IVehicle>

It's important to understand that an interface type is a (data) type like any other type although it just contains the method signatures but not any implementation.

A variable with an interface type can be assigned to any object that implements that interface.

The .Net runtime uses interfaces extensively. Many collection classes implement several interfaces. One of the most common interfaces is IEnumerable or IEnumerable.

The often used List class implements not only one but the total of eight interfaces:

  1. IList`1
  2. IList
  3. ICollection`1
  4. ICollection
  5. IEnumerable`1
  6. IEnumerable
  7. IReadOnlyList`1
  8. IReadOnlyCollection`1

The `1 stands for one generic type.

It's a good practice to categorize collections and their capabilities by looking at the interfaces they implement. Without the IList interface for example there will be no add or remove method because both methods are part of this interface. So if any listed class implements the IList interface, the add and the remove member is warranted by this contract.

Thanks to .Net reflection it's really simple to list the names of the interfaces any class implements in X# too. You only have to call the GetInterfaces() method of the type object that contains all the type metadata of an object.

**Example 11.25: (XS_GenericListInterfaces.prg) **

// listing the interfaces of a generic list class

using System.Collections.Generic

Function Start() As Void
   Local l1 := List<String>{} As List<String>
   Local t := l1.GetType() As Type
   ? String{'=',80}
   ? "All interfaces of a generic List<T>"
   ? String{'=',80}
   ForEach var I in t:GetInterfaces()
     ? I.Name
   Next

Abstract base classes, as alternative #3, are deliberately not part of this book. One reason is, that they are mostly needed in class libraries that should provide functionality for other developers. Second, I have not used them during the many years I have written code in X#.

And now: Polymorphism

In programming, polymorphism means that you can access objects of different types through the same interface. However, each type can provide its independent implementation of the methods of that interface.

The main question always is: How can two classes, in this example SpecialCar and Bus, become type compatible with a super class Car and, at the same time, a method of that superclass can be implemented differently in each derived class?

There are (at least) three alternatives:

  1. Inheritance with virtual methods
  2. Interfaces
  3. Abstract base classes

Alternative #2 means that both classes implement the same interface.

Achieve polymorphism through overriding virtual methods

Any method that is declared as virtual can be overridden in a derived class and therefore implemented differently. A virtual method can be replaced by another method with the same signature in a derived class.

The class Vehicle defines the Drive method as virtual.

Class Vehicle

   Internal Virtual Method Drive() As Void
        Console.WriteLine("I am driving a vehicle")

End Class

````

So it can be overridden in a derived class.

```C#
Class Car Inherit Vehicle

   Internal Override Method Drive() As Void
        Console.WriteLine("I am driving my DAF 44 Variomatic")

End Class

This has several implications. One of them is, that when an instance of car is assigned to a variable of vehicle, the Drive method call will call the overridden method.

// v will be of type vehicle
Local v := Vehicle{} As Vehicle
// c will be of type car
Local c := car{} As Vehicle
// Put both objects into a list
var l := List<Vehicle>{}
l:Add(v)
l:Add(c)
ForEach c1 As Vehicle in l
   c1:Drive()
Next

Example 11.26: (XS_VirtualMethod.prg) ** You will find the source code in the repository

Here are a few more facts about virtual methods:

  1. A virtual method is a type of method where the actual method calls depend on the runtime type of the underlying object.
  2. A non-virtual method is a type of method where the actual method depends on the reference type of the object at the point of method invocation.
  3. The runtime takes place over compile time.
  4. If the Override keyword is necessary for the derived class, may also depend on the compiler switch enforceoverride.
  5. It's not possible to call the base class implementation of an overridden method from outside the class.

NOTE: To be compatible with VO, Xbase++ and FoxPro, the compiler offers an option vo3 that makes all instance methods and properties virtual. Methods and properties in subclasses will automatically become "overrides" when they already exist in the parent class.


Achieve polymorphism through interfaces

Another option to achieve polymorphism is to define an interface (IVehicle in the example) with several methods or properties. An instance of a class that implements this interface (and all its methods) becomes compatible with instances of other classes that implement the interface as well.

**Example 11.27: (XS_PolymorphismWithInterfaces.prg) **

// An example for Polymorphism through interfaces
using System.Collections.Generic

Interface IVehicle
   Public Property Id As String Auto
   Public Method Drive(Distance As Single) As Void
End Interface

// Define independent classes
Class SUV Implements IVehicle
  Property Id As String Auto
  Method Drive(Distance As Single) As Void
    Console.WriteLine(i"{Self:Id}:My Lexus NX300 is ploughing its ways to the traffing with a distance of {Distance} km")

  Method ToString() As String
    Return i"Type SUV Id:={Self:Id}"

End Class

Class Car Implements IVehicle
  Property Id As String Auto
  Method Drive(Distance As Single) As Void
   Console.WriteLine(i"{Self:Id} is driving a distance of {Distance} km")
  Method ToString() As String
    Return i"Type SUV Id:={Self:Id}"

End Class

Function Start() As Void
  // Define instances of Car and SUV
  var car1 := Car{}{Id:="Car1"}
  var suv1 := Suv{}{Id:="SUV1"}
  // Create a generic List for objects that implement IVehicle
  Local vehicles := List<IVehicle>{} As List<IVehicle>

  // Add the instances to the list
  vehicles:Add(car1)
  vehicles:Add(suv1)

  // Enumerate the list of IVehicle objects
  ForEach var vehicle In vehicles
      // Achive polymorphis by calling the different implementation of the Drive() method
      vehicle:Drive(100)
      // Call the overwritten ToString() method too
      Console.WriteLine(vehicle:ToString())
  Next

The (small) benefit of polymorphism through interface inheritance is that the Drive() method of IVehicle can be called on different types of objects and each implementation can behave differently.

Polymorphism supports the famous "Open Closed principle". Uncle Bob says: "A class definition should be open for extension but closed for modification which means a change of its implementation".

Operator overloading

Operator overloading means that an operator like + can be used with different data types and behaves differently for each data type. The classic example is subtracting two DateTime values to get the difference as a TimeSpan object.

var ts := DateTime.Parse("24.12") - DateTime.Now ? ts:Days

In this example the minus operator is overloaded. Not every operator can be overloaded, but some operators can:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading#overloadable-operators

All it takes is a Operator keyword preceded by Static inside a class definition. The following example overloads the + operator so that two address objects can be added by instancing a new Address object with the name of each address as the constructor value.

Static Operator + (A1 As Address, A2 As Address) As Address
   Return Address{i"{A1.Name}-{A2.Name}"}

**Example 11.28: (XS_OperatorOverloading.prg) **

// Operator overloading the + operator for a reference type

Class Address
    Internal Property Name As String Auto

    Constructor(Name As String)
        Self:Name := Name

    Static Operator + (A1 As Address, A2 As Address) As Address
      Return Address{i"{A1.Name}-{A2.Name}"}

    Public Method ToString() As String
        Return i"Name={Self.Name}"
End Class

Function Start() As Void
    var a1 := Address{"Hugo"}
    var a2 := Address{"Boss"}
    ? a1 + a2

The (small) benefit of operator overloading is (one more time) more convenience and better readability because no "artificial" add method has to be used.