McBasic™Get McBasic™ ↗
Build 881
Hands-on · McBasic™ 0.5

Create, grow and test an array of objects

Build the data model first, then run four tests that distinguish array storage from object identity.

Step 1Make a safe Desktop App practice copy#

Extract the download and open ClassArrayPractice.mcproj. It is the finished solution: replace existing file contents when following along, rather than appending duplicate procedures. For a blank rebuild, choose Desktop App with one startup Form named frmMain. No account or network service is needed.

Step 2Declare the class, module and test file#

Add a standard module Main.bas, a class module Customer.cls named Customer and a unit-test module CustomerTests.bas. Set frmMain Caption to Class Array Practice, Width 500 and Height 200. Add lblResult (Label, Left 24, Top 24, Width 440, Height 60, Caption Choose Run demo., WordWrap True) and cmdRun (CommandButton, Left 24, Top 110, Width 140, Height 32, Caption Run demo, TabIndex 0). Keep Left/Top anchors, plus Right on the Label. File placement alone is not registration: confirm the declarations below in the project.

Complete ClassArrayPractice.mcproj
{
  "schemaVersion": 1,
  "projectId": "mcbasic-web-class-array-practice",
  "name": "ClassArrayPractice",
  "kind": "DesktopApp",
  "language": {
    "dialect": "McBasic1",
    "requireExplicit": true,
    "compare": "Binary",
    "defaultArrayBase": 0
  },
  "application": {
    "bundleIdentifier": "org.mcbasic.web.classarraypractice",
    "version": "1.0.0",
    "buildNumber": "1",
    "startupFormId": "main",
    "shutdownMode": "OnStartupFormClosed"
  },
  "forms": [
    {
      "id": "main",
      "typeName": "frmMain",
      "layout": "frmMain.form.json",
      "code": "frmMain.bas"
    }
  ],
  "modules": [
    {
      "name": "Main",
      "path": "Main.bas"
    }
  ],
  "classes": [
    {
      "name": "Customer",
      "path": "Customer.cls"
    }
  ],
  "tests": [
    {
      "name": "CustomerTests",
      "path": "CustomerTests.bas",
      "kind": "unit"
    }
  ],
  "references": [],
  "resources": [],
  "targets": [
    "osx-arm64"
  ],
  "capabilities": []
}

Step 3Understand the entry points#

Bind cmdRun.Click to cmdRun_Click(). The handler invokes Main.Main for diagnostic output and shows DemoNames() in the Label. MakeTeam returns Customer(); RenameSecond takes the array ByRef by default. Customer.RenameTo changes one instance and returns its new name length; the statement call deliberately ignores that result. Test procedures begin with Test_ and run through Test, not through the button.

Step 4Enter each complete file#

Start with the class, then the standard module, Form handler and tests. Keep Option Explicit once at the top of each file. Assign arrays with = and individual object references with Set.

Customer.cls — complete file
Option Explicit

Public Name As String

Public Function RenameTo(ByVal value As String) As Long
    Name = value
    RenameTo = Len(value)
End Function

Public Function Greeting() As String
    Greeting = "Hello, " & Name
End Function
Main.bas — complete file
Option Explicit

Public Function MakeTeam() As Customer()
    Dim people(1) As Customer
    Set people(0) = New Customer
    people(0).Name = "Ada"
    Set people(1) = New Customer
    people(1).Name = "Grace"
    MakeTeam = people
End Function

Public Sub RenameSecond(people() As Customer)
    people(1).RenameTo "Katherine"
End Sub

Public Function TeamNames(people() As Customer) As String
    Dim person As Customer
    Dim result As String
    For Each person In people
        If Not person Is Nothing Then
            If Len(result) > 0 Then result = result & ", "
            result = result & person.Name
        End If
    Next
    TeamNames = result
End Function

Public Function DemoNames() As String
    Dim people() As Customer
    people = MakeTeam()
    RenameSecond people
    ReDim Preserve people(2)
    Set people(2) = New Customer
    people(2).Name = "Dorothy"
    DemoNames = TeamNames(people)
End Function

Public Sub Main()
    Dim people() As Customer
    people = MakeTeam()
    Debug.Print "Team: " & DemoNames()
    Debug.Print "Greeting: " & people(0).Greeting()
End Sub
frmMain.bas — complete file
Option Explicit

Private Sub cmdRun_Click()
    Main.Main
    lblResult.Caption = DemoNames()
End Sub
CustomerTests.bas — complete file
Option Explicit

Public Sub Test_DemoNames()
    Assert.AreEqual "Ada, Katherine, Dorothy", DemoNames()
End Sub

Public Sub Test_DistinctInstances()
    Dim people() As Customer
    people = MakeTeam()
    Assert.IsFalse people(0) Is people(1)
    people(0).Name = "Changed"
    Assert.AreEqual "Grace", people(1).Name
End Sub

Public Sub Test_PreserveAndEmptyReference()
    Dim people() As Customer
    Dim first As Customer
    people = MakeTeam()
    Set first = people(0)
    ReDim Preserve people(2)
    Assert.IsTrue people(0) Is first
    Assert.IsTrue people(2) Is Nothing
    Assert.AreEqual "Ada, Grace", TeamNames(people)
End Sub

Public Sub Test_UnallocatedArray()
    Dim people() As Customer
    Dim person As Customer
    Dim failure As Long
    Try
        For Each person In people
            failure = -1
        Next
    Catch
        failure = Err.Number
    End Try
    Assert.AreEqual 9, failure
End Sub

Step 5Keep the example independent of external services#

No resource, migration or package is required. The names exist only in memory. Each MakeTeam call creates new instances; assigning an existing reference into another slot would instead alias the same object. ReDim Preserve preserves references, not independent copies of their contents.

Step 6Run the example and its tests#

Save, Check, then Run and click Run demo. The Label must show Ada, Katherine, Dorothy. IDE output also includes Team: Ada, Katherine, Dorothy and Greeting: Hello, Ada. Choose Test: all four test procedures must pass. The unallocated-array test expects error 9, so catching that error is the successful result.

Optional developer CLI, from the extracted folder
mcbasic check ClassArrayPractice.mcproj
mcbasic run ClassArrayPractice.mcproj
mcbasic test ClassArrayPractice.mcproj

Temporarily change the expected names in Test_DemoNames, run Test and observe the failure. Restore the expected value and rerun; a green Check alone never proves these assertions ran.

Step 7Grow without losing identity#

Take a Git checkpoint, expand to index 3 and instantiate the new slot. Update the result test and add an assertion that the first Customer is still the same object after Preserve. Keep the Nothing check in TeamNames. Compare typed object arrays and control references before trying to store instances in a Collection.

Source baseline 20f4bfed6b · Build manifest
Sources & maintenance

Original web explanation, reviewed against these repository sources. API tables and example files follow the implementation.

  • docs/manual/21-language-reference.md
  • tests/McBasic.Compiler.Tests/ClassArrayChecks.cs
  • tests/McBasic.Compiler.Tests/ControlTypeChecks.cs
  • tests/McBasic.Compiler.Tests/ControlsCollectionChecks.cs
  • site/examples/ClassArrayPractice/ClassArrayPractice.mcproj
  • site/examples/ClassArrayPractice/Main.bas
  • site/examples/ClassArrayPractice/Customer.cls
  • site/examples/ClassArrayPractice/CustomerTests.bas
  • site/examples/ClassArrayPractice/frmMain.bas
  • site/examples/ClassArrayPractice/frmMain.form.json