はじめに

この記事では、クラスの「動作」を担うメソッドについて説明します。

VBAでクラスを活用するうえで、メソッドの設計は極めて重要です。

特に Public(公開)Private(非公開) の使い分けが、クラスの「使いやすさ」や「修正や拡張のしやすさ」を大きく左右します。

VBAクラスにおけるメソッドとは

メソッドとは、クラス内で定義する Sub または Function のことです。標準モジュールに作成する自作関数と構文は同じですが、クラスでは意味や使い方に違いがあります。

クラスが保持するデータに対して、どういう「処理」を提供するかを定義するのがメソッドです

クラスのプロパティが「クラスの状態」を表すのに対して、メソッドはクラス内部に保持されたデータに対する「操作(例えば、データを追加・更新・削除するなど)」を担当します

命名には、動作を示す動詞をメソッド名の先頭に使うのが一般的です。

例:
・CalculateTotal
・PrintInfo
・LoadFromSheet

PublicメソッドとPrivateメソッドの違い

メソッドは Public または Private のいずれかで定義できます。この指定によって、クラスの外部から呼び出せるかどうかが決まります。

なお、PublicとPrivateのどちらも指定しなかった場合は暗黙でPublicとして扱われます。ただ、指定せずに暗黙のPublicにするのはやめましょう

というのも、第三者が見たときに「Publicの書き忘れなのか? それとも意図的に暗黙のPublicにしているのか?」をコードから判断しなければなりません。そのため、将来クラスを拡張する際に、余計な確認の手間がかかってしまいます。このような弊害があるため、PublicまたはPrivateは必ず記述するようにしましょう

Publicメソッド

Publicメソッドは外部から呼び出せるメソッドです。クラス利用者に対して提供する「サービス」的な役割を持ちます。

Publicにするメソッドは、「公開する必要に迫られている場合」のみ公開します。

ちょっとおかしな例ですが、こちらの質問に対して素直に回答を返してくれる人と、質問とは関係ない回答や聞いてもいないことをバンバン話してくる人と、どちらが話しやすいでしょうか。当然前者です。

クラスのメソッドの設計も同様で、外部から「クラス内部のデータはこのように扱いたい」という要望を受け付ける窓口としてPublicメソッドを用意します。外部から使われないものはPublicメソッドにするべきではありません。

例:

Privateメソッド

Privateメソッドはクラス内部でのみ使用するメソッドです。複雑な処理を分割して整理したり、再利用性を高めたりするために使います。

通常なPublicメソッドから呼び出される内部処理として利用します。

例:

実例:StringListクラスのメソッド設計

実際にStringListというクラスを例に、メソッドの設計でのPublic(公開)とPrivate(非公開)について説明します。

StringListクラスは文字列の配列を使いやすくしたクラスです。プログラミング経験者であれば、JavaのArrayListや、C#のListのようなものの簡易版と思ってください。

クラス内に保持するデータとして、文字列のコレクションを用意し、Publicメソッドで文字列コレクションの操作を行っています。

以下のコードは簡易版ですが、VBAでArrayListのように使えるコードを「VBAでArrayListクラス」ページで紹介していますので興味があればご参照ください。

コード説明

  • Add: 文字列コレクションに1つ追加します。
  • GetItem(index): 指定位置の要素を取得(インデックスは 1 始まり)。
  • Count: 要素数を返します。
  • ShowAll: 文字列コレクションの全件出力(Debug.Print)。
  • DebugInternalState: クラス内部でのみ使える Private メソッドです。

このクラスは、C# で言えば List に、Java で言えば ArrayList に相当する使い方が可能です。ここからさらに、要素を削除するRemove(index)や、全件削除のClear()や、指定文字列が含まれているか判定するContains(value)などの公開メソッドを追加すると、実際に実用可能なクラスになります。

StringListクラスの使用例(標準モジュール)

StringListのPublicメソッドを順に使ったサンプルコードです。Add()でデータを追加し、そのあとに要素数の出力、2番目の要素の取得を行い、最後にリストの全件を出力しています。

実行結果(イミディエイトウィンドウに出力されます)
要素数: 1
要素数: 2
要素数: 3
要素数: 3
2番目の要素: Banana
Apple
Banana
Cherry

役割を分けて、テストしやすくする

良いメソッド設計の原則の1つに「1メソッド=1つの処理」があります。処理が長くなっている場合は、内部の手続きを Private メソッドに分割しましょう。

また、メソッド名と掛け離れた処理を行うのも、避けましょう。

例:

pName や pAge はクラスのメンバー変数(Private変数)だと仮定しています。クラス内でフォーム入力結果などを一時的に保持している想定です。

IsValidAge を分けておくことで、例えば単体テスト時に年齢の条件だけを集中的にテストすることができ、意図しない副作用を防ぎやすくなります。

このようにPublicメソッドの中の処理をPrivateメソッドとして分離することで、コードの見通しが良くなり、内部処理の内容が明確になり、将来の拡張やテストも簡単になります。

よくあるミスと改善例

悪いケース 改善案
すべてのメソッドをPublicにする。 外部に必要なものだけをPublicにする。
メソッドが1つで処理が複雑。 処理ごとにPrivateメソッドへ分割する。
メソッド名が曖昧。(例:Data6) 動詞から始まる名前にする。(例:LoadData)

おわりに

クラスにおけるメソッドの設計は、単にコードの「動作」を書く以上に、「何を外部に公開し、何を隠すか」という設計思想が問われる重要なポイントです。

何を公開すべきか、を迷う場合は、クラスが保持する内部データをどうしたいのか、という点に着目すると、どのような公開メソッドがふさわしいか見えてきます。

Public と Private を意識した役割分担ができるようになると、コードの見通しや保守性が格段に向上します。少しずつでも意識して設計する習慣を身につけていきましょう。