私は実際に最初の[〜#〜] vba [〜#〜]プロジェクトに取り組んでいます。 (C++から来る)
クラスとポリモーフィズムを実装することにより、既存の[〜#〜] vba [〜#〜]Microsoft Excelワークブックで使用されるプロジェクトを改善したいと思います。
私の問題は:
1-[〜#〜] vba [〜#〜]はオブジェクト指向プログラミングではないことを説明する多くの記事/フォーラムを読みました( [〜#〜] oop [〜#〜])言語であり、多態性をサポートしていません。
それらのいくつかは、キーワードImplementsを使用して回避策を提案します。
2-また、 this one のようなWebページを見つけました。これは、OOPおよびキーワードを使用したVBAのポリモーフィズムの実行方法を説明しますlikeInherits、Overrides、Overridable、 MustOverrides。
だから私の質問は:
[〜#〜] vba [〜#〜]は[〜#〜] oop [〜#〜]言語であり、ポリモーフィズムをサポートしていますか?
OOPは4つの「柱」に座っています。
Abstraction-class modulesでオブジェクトを定義することにより、ロジックと概念を簡単に抽象化できます。厳密に言えば、abstractionは、意味のある識別子を使用し、手続きコードをメソッド(クラスメンバー)に抽出することでも実現されます。
abstractionを示すVBAで記述されたプロシージャの例を次に示します。
_Public Sub Test(ByVal checkin As Date, ByVal checkout As Date, ByVal custType As CustomerType)
Dim Finder As New HotelFinder
InitializeHotels Finder
Debug.Print Finder.FindCheapestHotel(checkin, checkout, custType)
End Sub
_
abstraction levelは非常に高いため、このTest
プロシージャが何をしているのかが一目でわかります:implementation detailsはabstractedで、より特殊なオブジェクトとメソッドになります。
カプセル化-クラスはプロパティによって公開されるプライベートフィールドを持つことができます。クラスをPublicNotCreatable
にして、型を他のVBAプロジェクトに効果的に公開します-クラスモジュールをエクスポートし、お気に入りのテキストエディターで開き、クラス属性を手動で編集し、モジュールを再インポートすることで、実際の読み取り専用タイプを実現できます。パラメーター化されたコンストラクターがないという事実は無関係です-好きなパラメーターをすべて取得してインスタンスを返すファクトリーメソッドを記述するだけです。これはCOMであり、COMはとにかく工場が好きです。
上記のスニペットencapsulatesHotelFinder
オブジェクトのCollection
クラスがSet
オブジェクトを介して、_Property Get
_アクセサーを介してのみ公開する方法の例を次に示します。この参照、encapsulated:
_Private Type TFinder
Hotels As Collection
End Type
Private this As TFinder
Public Property Get Hotels() As Collection
Set Hotels = this.Hotels
End Property
Private Sub Class_Initialize()
Set this.Hotels = New Collection
End Sub
Private Sub Class_Terminate()
Set this.Hotels = Nothing
End Sub
_
Polymorphism-Implements
を使用すると、抽象インターフェース(および具象クラスも)を実装できます。その後、同様にできるISomething
抽象化に対してコードを記述できますFoo
またはBar
(与えられたFoo
とBar
は両方ともISomething
を実装します)-これまでに必要なコードはすべてISomething
です。メソッドのオーバーロードはVBAにはない言語機能ですが、オーバーロードはポリモーフィズムとは関係がありません。これは基本となる異なるフォーム(データ型)に対して同じインターフェイスを提示する機能。
ここに適用されたポリモーフィズムの例があります-_LogManager.Register
_メソッドは、ILogger
インターフェイスを実装する任意のオブジェクトで動作します;ここでDebugLogger
とFileLogger
-そのインターフェイスの大きく異なる2つの実装が登録されています。後でLogManager.Log(ErrorLevel, Err.Description)
が呼び出されると、2つの実装はそれぞれ独自の処理を行います。 DebugLogger
はimmediateツールウィンドウに出力し、FileLogger
は指定されたログファイルにエントリを書き込みます。
_LogManager.Register DebugLogger.Create("MyLogger", DebugLevel)
LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:\Dev\VBA\log.txt")
_
Inheritance-VBAでは、別の型から派生させることはできません。継承はサポートされていません。
問題は、継承をサポートしていない言語を「オブジェクト指向」として修飾できるかどうかです。composition は、多くの注意事項がある継承よりも望ましい場合が非常に多くあります。また、VBAを使用すると、composeオブジェクトを思いのままに作成できます。
VBAはOOP言語ですか?
欠けているものはすべて継承であり、その構成は継承よりも望ましいことを考えると、「はい」と答えたいと思います。以前に本格的なOOP VBAコード(作業単位とリポジトリを備えたModel-View-Presenter、誰か?)を書いたことがあります。これは、「実際のOOP "継承をサポートする言語。
以下にいくつかの例を示します。すべて100%VBAです。
この最後のリンクのコードは最終的にC#に移植され、すぐに VBA IDEのCOMアドイン に進化しました。これにより、リファクタリング、ナビゲーションの改善、コード検査、その他のツールが提供されます。
VBAは、あなたが作る限り制限されます。
短い答えはノーとノーです。
VBAはオブジェクトベースであるため、クラスを定義してオブジェクトのインスタンスを作成できますが、通常、完全なOOP言語に関連付けられる機能はありません。たとえば:
Class_Inititalize
何らかの構築はできますが、引数を取ることができないイベント。引数を渡すにはpublic factory function が必要になりますが、コンストラクタースタイルのデザインパターンを作成するには回避策が必要です。Implements
を使用して)インターフェイスを介してある程度達成できますが、関数をオーバーロードする機能は存在せず、各「オーバーロード」には技術的に一意の関数名が必要です。この問題を回避するには、オブジェクトを関数またはサブルーチンへの唯一のパラメーターとして渡し、プロパティの値に応じて手順を変更します。したがって、オブジェクトをある程度操作でき、MS Officeアプリケーションはオブジェクトモデルに基づいていますが、VBAはオブジェクト指向言語ではありません。多態性は、C++で熟知している範囲では実現できません。