プロパティとメソッドの上書き

ベースクラスで定義されたプロパティまたはメソッドは、派生クラスで使用できます。また、派生クラスで使用されるベースクラスのプロパティとメソッドの動作のモデルを変更することもできます。これは、プロパティの上書きやメソッドの上書きと呼ばれます。

派生クラスでプロパティを再定義することにより、ベースクラスのプロパティを上書きします。同様に、派生クラスでサブルーチンまたは関数を再定義することにより、メソッドを上書きします。上書きするメソッドの先頭部は、ベースクラスのメソッドの先頭部と同じでなければなりません。派生クラスのメソッドに対するパラメータは、ベースクラスのメソッドに対するパラメータと正確に一致する必要があります。

次の例では、継承によって関連する 2 つのクラス作成します。スクリプトは Fruit という名前のベースクラスを宣言し、続いて Fruit クラスから新しく Apple クラスと Banana クラスを派生させます。Apple クラスと Banana クラスは Fruit クラスのすべての変数 (weight と color) と Prepare サブルーチンを継承します。

Prepare サブルーチンはベースクラスでは意図的にブランクになっています。このサブルーチンは一般的なアクセスを提供し、Fruit サブルーチンを介して Apple または Banana の特性にアクセスできるように、派生クラスで上書きまたは拡張できます。これらの派生クラスは両方ともベースクラスの Prepare サブルーチンを上書きします。Apple クラスは Core サブルーチンで置き換え、Banana クラスは Peel サブルーチンで置き換えます。

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

派生クラス用の Sub New を拡張する

Sub New を派生クラス用に定義して、ベースクラスの Sub New 定義を拡張できます。派生クラス用の Sub New は、ベースクラスの Sub New をパラメータも一緒に提供する必要があります。

ベースクラスの Sub New のパラメータリストは、派生クラスの Sub New のパラメータリストのサブセットになります。モジュールレベルで宣言された定数や変数も含め、任意の式をベースクラスの Sub New に対する引数として渡すことができます。派生クラス用の Sub New の引数とベースクラス用の Sub New の引数が同じであれば、ベースクラスの Sub New の引数を省略できます。

構文は次のとおりです。

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

[ statements ]

End Sub

要素

説明

paramList

Sub New のパラメータ宣言のリスト (カンマ区切り)。各パラメータ宣言には、次の構文を使用します。

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

ByVal は、paramName を値渡しします。paramName に代入された値は、その値へのポインタではなく、メモリ内の値のローカルコピーです。paramName() は配列変数です。List は paramName をリスト変数として識別します。それ以外の場合、paramName には LotusScript® でサポートされるその他すべての型の変数を指定できます。As dataType は変数のデータ型を指定します。

baseClass

クラスの派生元のクラスの識別子です。baseClass は派生クラスの Class ステートメント中の baseClass と同じでなければなりません。

baseArgList

ベースクラスの Sub New 用の引数のリスト (カンマ区切り)。これらの引数は、baseClass の Sub New に渡されます。ベースクラスの Sub New に対する引数が派生クラスの Sub New に対する引数と、数値やデータ型で一致しない場合、または派生クラスの Sub New に渡される引数とは異なる引数を baseClass の Sub New に渡す場合、この引数リストを指定します。

次の派生クラスの Sub New は、モジュールレベルで宣言された 2 つの変数をベースクラスに渡します。

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.

Sub New と Sub Delete を呼び出す

派生クラスのオブジェクトが作成されるとき、派生クラスの Sub New への呼び出しがベースクラスの Sub New への呼び出しを生成します。そのベースクラスも派生クラスであれば、そのベースクラスへの呼び出しが生成されます。すべての呼び出しの後で最高レベルの Sub New が実行され、続いて派生チェーン内の各クラスの Sub New が次々に実行されます。作成中のオブジェクトのクラスの Sub New は最後に実行されます。

派生クラスのオブジェクトが削除されるとき、派生クラスの Sub Delete が呼び出されて実行された後にベースクラスの Sub Delete が呼び出され、最高レベルのベースクラスまで派生チェーン内の各クラスの Sub Delete が次々に呼び出されます。つまり、実行順序は Sub New の場合とは逆になります。

次の例では、Sub New と Sub Delete が呼び出される順序を示しています。

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.

ベースクラスのプロパティとメソッドにアクセスする

派生クラスでメソッドが上書きされていたとしても、派生クラスはベースクラスのプロパティやメソッドを呼び出すことができます。ベースクラスの上書きされたメソッドにアクセスするには、2 つのドット (ドット表記法) を使用します。2 つのドットを使用する表記法はクラスのスコープ内 (Class ステートメント内) だけで有効です。

構文は次のとおりです。

baseClassName .. propertyName (parameters)

または

baseClassName .. methodName (parameters)

例えば、処理を追加するためだけにメソッドを上書きすることもできます。その場合、ベースクラスのメソッドを呼び出し、続いて派生クラスのメソッド内で追加処理を実行します。

オブジェクト参照を引数と戻り値として使用する

オブジェクト参照は、メソッドに対する引数として、またはそれを受け付けるように定義されたプロシージャに対する引数として渡すことができます。プロシージャの戻り値としてオブジェクト参照を使用することもできます。LotusScript ではオブジェクトは値渡しではなく、参照渡しされます。

オブジェクト参照をプロシージャに渡すときは、次の規則を念頭に置いてください。

次の例では、オブジェクトを引数としてとるために、モジュールレベルで PrintAccount サブルーチンを定義しています。

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)

派生クラスオブジェクトで Set ステートメントを使用する

派生クラスオブジェクトへの参照を含む変数を、そのオブジェクトの任意のベースクラスへの参照を含むことのできる変数に割り当てられます。例えば、CheckingAccount クラスは Account クラスから派生しているため、CheckingAccount 型の変数の値を Account 型の変数に代入できます。

ベースクラスの変数内の参照を、派生クラスのオブジェクトを参照する変数に割り当てることはできません。例えば、Account クラスの変数の中の参照を CheckingAccount クラスの変数に代入することはできません。このような代入ができてしまうと、ユーザーは参照されるオブジェクトに CheckingAccount のメソッドを使用できると期待するかもしれません。しかし、オブジェクトは Account クラスのものかもしれないため、メソッドは存在しないことがあります。

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

最後のステートメントは、正しくありません。なぜなら、Set X = Z ステートメントの後で、変数 X が派生クラス CheckingAccount のオブジェクトを参照しています。しかし、ステートメント Set Z = X はベースクラスのオブジェクト参照変数 X の値を派生クラスのオブジェクト参照変数 Z に割り当てようとします。