PublicNotCreatableの意味

PublicNotCreatableの意味

クラスモジュール使いであっても、あっちこっちで使い回すようなクラスモジュールを作ったりしなければ、存在にすら気づかないのが、クラスモジュールのInstancingプロパティではなかろうか。

Instancingプロパティに、「Private」と「PublicNotCreatable」の二種類の設定値があることは知っていたが、余り深く意味を考えたことがなかった。

特に、「PublicNotCreatable」の方は、「NotCreatable」の文字だけを見て、

インスタンスが作れねえのかよ、不便だな

とか、わけのわからない理解をしていた。

ちょっとづつわかってきたかも知れないので、メモ。

Private/Publicの違い

まず、「Private」と「Public」の違い。

これは、

別プロジェクトに対して

Private」か「Public」か、ということ。

VBAによるマクロ作成の場合、1ブック(プロジェクト)内で閉じた処理であることが多いので、普通に使っている限り、まず意識することがないポイントだと思う。

たとえば、

f:id:akashi_keirin:20190623083527j:plain

このようなプロジェクト構成になっているとする。(おい、ファイル名は綴りが間違えてるじゃねえかw)

Referring」というプロジェクトが、「Referred」というプロジェクトを参照している。

参照しているということは、「Referring」(参照元)から「Referred」(参照先)へのつながりをつけているということ。

つながりがついているから、「Referring」(参照元)からは、「Referred」(参照先)の中の「Public」なものについては〈見える〉(呼び出せる)ということになる。

ここで言う〈見える〉というのは、コードウインドウ等に〈表示できる〉ということではない(それは、〈ユーザーから見える〉ということだ)。

再度、プロジェクト エクスプローラー画像を。

f:id:akashi_keirin:20190623083527j:plain

ご覧のとおり、参照先である「Referred」には、「HogePrivate」と「HogePublic」という二つのクラスモジュールが置かれている。

クラス名からも明らかなとおり、「HogePrivate」は、Instancingプロパティを「Private」に、「HogePublic」の方は「PublicNotCreatable」に設定している。

f:id:akashi_keirin:20190623083530g:plain

ご覧のように、入力時のヒントには「HogePublic」の方しか出てこない。

これが、〈見える〉ということだ。

Referringプロジェクトからは、Referredプロジェクト内のクラスのうち、PrivateHogePrivateクラスは〈見えない〉が、PublicHogePublicクラスは〈見える〉ということだ。

では、NotCreatableとは

最初、「NotCreatable」という字面から、「インスタンスが作れないクラス」のことだと思っていた。

しかし、Instancingプロパティを「PublicNotCreatable」に設定していても、普通にNewインスタンス化することができていたので(当たり前)、「わけわからんなー」で済ませていたのだった。

これは要するに

別プロジェクト内でインスタンスが作れない

ということだったのだ。

今回の例の場合だと、

Referringプロジェクト上で、Referredプロジェクト下のクラスのインスタンスを作ることはできない

というだけのことだった。

f:id:akashi_keirin:20190623083538g:plain

このように、「不正」呼ばわりされて、インスタンスが作れないのだ。

もちろん、上の例での変数hogeインスタンスをぶち込む方法はある。

これまで当ブログのコメント欄等でも言及があったように、参照先(クラスを持っている側のプロジェクト。今回の例で言うとReferredプロジェクト。)にインスタンスを返すメソッドを置いておけば良い。

参考までに今回の例の場合だと、次のようなメソッドを置くことになる。

リスト1 ReferredプロジェクトのThisWorkbookモジュール
Public Function getHogeinstance() As HogePublic
  Set getHogeinstance = New HogePublic
End Function

そして、参照元HogePublicクラスを呼び出す側のプロジェクト。今回の例で言うとReferringプロジェクト。)で次のように書く。

スト2 Referringプロジェクトの標準モジュール
Dim hoge As HogePublic
Set hoge = Referred.ThisWorkbook.getHogeInstance

ちなみに、ThisWorkbookの後に「.」(ピリオド)を入力してもヒントが出ないので不安になるが、大丈夫。

おわりに

最初にも書いたとおり、そもそもVBAでは、複数プロジェクトにまたがるような処理を書くことがあまりないので、

Privateに対するPublicはあるのに、NotCreatableに対するCreatableがない

という非対称性に気づく機会が少ないのだと思う。

汎用的なオレオレメソッドが溜まってきて、それをあちこちで使い回そうという気持ちになったときに、初めてぶつかる問題なのかも。