Property and method overriding

A property or method defined in a base class is accessible in the derived class. You can also modify the behavior of the base class properties and methods used by the derived class. This is called property overriding and method overriding.

You override a base class property by redefining a property in the derived class. You override a method by redefining a sub or function in the derived class. The signature of the overriding method must be identical to that of the base class method. That is, the parameters to the method in the derived class must match exactly the parameters to the method in the class in which it was originally defined.

The following example creates two classes that are related by inheritance. The script declares a base class named Fruit, and then declares Apple and Banana to be new classes derived from the Fruit class. The Apple and Banana classes inherit all of the Fruit class's variables (weight and color) and the Prepare sub.

The Prepare sub is intentionally left blank in the base class. It provides general access and allows itself to be overridden and extended in the derived classes so that you can access Apple or Banana functionality via a Fruit sub. Both derived classes override the base class's Prepare sub. The Apple class substitutes a Core sub and the Banana class substitutes a Peel sub.

Class Fruit
weight As Single
color As String
  Sub New(w As Single, c As String)
    weight! = w!
    color$ = c$
  End Sub

  Sub Prepare  
    ' Assume that each derived class will override
    ' the Prepare method.
    ' Print a message...
    Print "The Fruit class's Prepare sub doesn't do anything."
  End Sub

End Class

Class Apple As Fruit ' Derive the Apple class from the 		'Fruit class.
  seedCount As Integer
  variety As String
   Sub Core          ' Add a Core sub to the Apple class.
     If (weight! > 5) Then  ' You can access base class members.
     Print "This apple core method is for apples " & _
       "of 5 lbs. or less." 
     Exit Sub
     End If
     '...
     Print "The ";weight!;" lb. ";color$;" "; variety$; _
        " apple is cored."
   End Sub

   Sub New(w As Single, c As String, v As String, _
      s As Integer), Fruit (w!,c$)
    Variety$ = v$	   ' Initialize the variety.
    SeedCount% = s%	   ' Initialize the number of seeds.
   End Sub
   Sub Prepare
      Core     ' To prepare an apple, you core it.
   End Sub
End Class

Class Banana As Fruit 
' Banana class is derived from the Fruit class.
   Sub Peel  ' Add a peel method to the Banana class.
     '.
     Print "The ";weight!;" lb. ";color$; _
" Banana is now peeled."
   End Sub
  Sub New(w As Single, c As String)
    '...
  End Sub
   
  Sub Prepare
    Peel               ' To prepare a banana, you peel it.
  End Sub
End Class

Extending Sub New for derived classes

You can define Sub New for a derived class to augment the Sub New definition of its base class. Sub New for a derived class must provide the base class Sub New with its expected parameters.

The parameter list for the Sub New of the base class can be a subset of the parameter list for the Sub New of the derived class. You can pass any expression, including a constant or a variable declared at module level, as an argument to the base class's Sub New. You can omit the arguments for the Sub New of the base class if the arguments for the derived class Sub New and the base class Sub New are the same.

The syntax is:

Sub New [ ( paramList ) ] [ , baseClass ( baseArgList ) ]

[ statements ]

End Sub

Element

Description

paramList

A comma-separated list of parameter declarations for Sub New. Use this syntax for each parameter declaration:

[ ByVal ] paramName [ ( ) | List ] [ As dataType ]

ByVal passes paramName by value: that is, the value assigned to paramName is a local copy of a value in memory, rather than a pointer to that value. paramName() is an array variable; List identifies paramName as a list variable; otherwise, paramName can be a variable of any of the other data types that LotusScript® supports. As dataType specifies the variable's data type.

baseClass

An identifier of the class from which the class is derived. baseClass must be the same as the baseClass in the Class statement for the derived class.

baseArgList

A comma-separated list of arguments for the Sub New of the base class. These arguments are passed to the Sub New of the baseClass. Specify this argument list if the arguments to Sub New of the base class do not match those for Sub New of the derived class in number and/or data type; or if you want to pass arguments to the baseClass's Sub New that are different from those passed to the derived class's Sub New.

This derived class Sub New passes two variables declared at module level to the base class.

Class Fruit
  Public weight As Single
  Public color As String
  Sub New(w As Single, c As String)
    weight! = w!
    color$ = c$
    Print "Fruit New() weight = ";w!, "color =";c$
  End Sub
End Class

Class Banana As Fruit
  Sub Peel   
  '...   
  End Sub

  ' Banana accepts only a weight.  The Sub New passes both
  ' weight and color to the base class (Fruit).
  Sub New(w As Single), Fruit (w, "Yellow")
    '...
    Print "Banana New() Weight = ";w!
  End Sub
End Class

Dim z As New Banana (0.45)   ' Create a .45 lb yellow banana.

Calling Sub New and Sub Delete

When LotusScript® creates an object of a derived class, the call to the Sub New for the derived class generates a call of the Sub New for the base class. If that base class is itself a derived class, LotusScript® calls its base class, and so on. After all the calls, the highest-level Sub New is executed followed by the Sub New of every class in the derivation chain. The Sub New of the class of the object being created is executed last.

When LotusScript® deletes an object of a derived class, it calls the Sub Delete for the derived class, followed by the Sub Delete of the base class Sub Delete, and so on for every class in the derivation chain, up to the highest base class; that is, in the reverse order of the Sub New execution.

This example shows the order in which Sub New and Sub Delete are called.

Class Fruit
  Public weight As Single
  Public color As String
 
   Sub New(w As Single, c As String) 
    weight! = w!
    color$ = c$
    Print "Fruit: New"
   End Sub
 
  Sub Delete
    Print "Fruit: Delete"
  End Sub
End Class

Class Apple As Fruit
  Public seedCount As Integer

  Sub Core
  ' ...
  End Sub 

  Sub New(w As Single, c As String)
    Print "Apple: New"
  End Sub
 
  Sub Delete
    Print "Apple: Delete"
  End Sub

End Class

Dim y As New Apple(1.14, "Red")	
' Executes Fruit's Sub New and then Apple's Sub New.

Delete y
' Executes Apple's Sub Delete and then Fruit's Sub Delete.

Accessing base-class properties and methods

A derived class can call a property or method in a base class, even if that method was overridden in the derived class. You use two dots (dotdot notation) to access a base class's overridden method. Dotdot notation is valid only in class scope (within a Class statement).

The syntax is:

baseClassName .. propertyName (parameters)

or

baseClassName .. methodName (parameters)

For example, you can override a method just to add additional processing. You would call the base class's method and then do the extra processing in the derived class method.

Using object references as arguments and return values

You can pass an object reference as an argument to a method, or to any procedure defined to accept it. You can also use an object reference as the return value of a procedure. LotusScript® passes objects by reference, not by value.

Keep these rules in mind when you pass an object reference to a procedure:

  • You can pass a reference to a derived-class object to a procedure if the procedure parameter is declared as a variable of the base class.
  • You cannot pass a reference to a base-class object if the procedure's parameter is declared as a variable of the derived class.

This example defines the PrintAccount sub at module level to take an object as an argument.

Class Account
  Sub DepositMoney 
    Print "In Account's DepositMoney sub."
  End Sub
End Class

Class CheckingAccount As Account
  Sub DepositMoney
    Print "In CheckingAccount's DepositMoney sub."
  End Sub
End Class

Sub PrintAccount(AccountArg As Account)
  Call AccountArg.DepositMoney
End Sub

Dim X As New Account
Call PrintAccount(X)      'Calls Account's DepositMoney method.

Dim Y As New CheckingAccount
' Calls CheckingAccount's DepositMoney sub. Y is legal as an 
' argument to PrintAccount, because CheckingAccount is a
' derived class of Account.
Call PrintAccount(Y)

Using the Set statement with derived class objects

You can assign a variable that contains a reference to a derived-class object to a variable that can contain a reference to any of that object's base classes. For example, you can assign the value of a variable of type CheckingAccount to a variable of type Account because the CheckingAccount class is derived from the Account class.

You cannot assign a reference in a variable of a base class to a variable that refers to an object of a derived class. For example, you cannot assign a reference in a variable of the Account class to a variable of the CheckingAccount class. If such an assignment were allowed, you might expect to be able to use CheckingAccount's methods on the referenced object. But they might not exist, since the object might be of the Account class.

Class Account
  '...
End Class

Class CheckingAccount As Account
  '...
End Class

Dim X As New Account
Dim Y As New Account
Dim Z As New CheckingAccount
' Legal assignment of the contents of a base-class variable           ' to a base-class variable
Set X = Y
' Legal assignment of the contents of a derived-class variable        ' to a base-class variable
Set X = Z
' Cannot assign base-class variable to derived-class variable.
Set Z = X          ' Illegal

The last statement is illegal because, following the Set X = Z statement, the variable X references an object of the derived class, CheckingAccount. But the statement Set Z = X attempts to assign the value of a base class object reference variable, X, to a derived class object reference variable, Z.