クラスとオブジェクトの違いとは?
「クラス」と「オブジェクト」という言葉は、VBAだけでなく多くのオブジェクト指向プログラミング言語でも使われます。
ただし、VBAでは「オブジェクト」は他の言語と比べるとかなり多用されます。
一般的な説明では、
- クラスは「設計図」
- オブジェクトは「設計図から作られた実体(使えるもの)」
と言われます。
ただ、私自身は、
- クラスは「料理のレシピ」
- オブジェクトは「レシピを見て作った料理」
と言った方が伝わるのになあ、と思ってます。
VBAのクラスモジュールで以下のような自作クラスを作ったとします。
1 2 3 4 5 6 7 8 |
'// Classモジュール: Person Option Explicit Public Name As String Public Sub SayHello() MsgBox "こんにちは、" & Name & "さん" End Sub |
このクラスを使うには、次のように標準モジュールから呼び出します。
1 2 3 4 5 6 7 8 |
Option Explicit Sub ClassTest() Dim p As Person Set p = New Person '// この"p"が「オブジェクト」 p.Name = "鈴木" p.SayHello End Sub |
このとき、New Person によって クラスからオブジェクト が生成されています。このオブジェクトのことを他言語では「インスタンス」と呼びます。
インスタンスという言葉はVBAではほとんど使われない
他言語ではクラスから生成されたものを「インスタンス」と呼ぶのが普通ですが、VBAでは通常「オブジェクト」と呼びます。それには理由があります。
用語 | 他言語 (Java/C#/Python) | VBA |
---|---|---|
クラス | クラス | クラスモジュール |
インスタンス | インスタンス | オブジェクト |
例えば、セルを表すRangeを使った以下のようなコードがあるとします。
1 2 |
Dim r As Range Set r = Worksheets("Sheet1").Range("A1") |
この”r”は「Rangeオブジェクト」と呼ばれます。「Rangeインスタンス」とは言いません。
オブジェクト指向プログラミング言語を習得している人でも、なぜVBAが「インスタンス」と言わずに「オブジェクト」と呼ぶのかは疑問が出てくると思います。
これにはVBAの場合は母体となるOffice製品が関わっています。次項で詳しく説明します。
VBAではなぜ「オブジェクト」と呼ぶのか
1. Officeの部品はNewしなくても使える
VBAはOffice製品をよりよく扱うためのツールのため、Office独自の部品があります。
それは、ブック(Workbook)やシート(Worksheet)やセル(Range)といったExcel操作をするために用意された専用の部品です。WordやAccessなどにも同様に独自の部品が用意されています。
これらのOffice専用部品は、自作クラスやDictionaryクラスなどのようにNewステートメントをして領域を確保(インスタンス化)しなくても利用できるようになっています。
なお、Newとは、そのクラスが用意しているデータ部分の領域を確保して、データを格納できるようにする処理のことです。これを他言語ではインスタンス化と言います。
1 2 |
Dim r As Range Set r = Range("A1") '// Office部品は"New"が無くても利用できる |
2. RangeなどのOffice部品は「クラス」でもあり「インスタンス」でもある
技術的な話で言えば、Rangeなどの部品はExcel VBAが提供している組み込みクラスで「Rangeクラス」です。当サイトの他の記事でも「Rangeクラス」と書いているのはそれが理由です。
ところが、このRangeクラスを実際に利用する場合には、すでに対象となるセルは開いているブックとシートの中に存在しているため、Excel側で「VBAでRangeを使うときは開いているブックのセル範囲を参照するのが当然なので内部でRangeクラスの領域にセル範囲を割り当ててインスタンス化する」という動作を行っています。
これによりVBAでRange等のOffice部品を使うときにNewを書く必要が無くなっています。
RangeであればA1セル、Worksheetであれば”Sheet1″などの実際のデータを持っているため、コードではNewしてないけどインスタンス化されている、という挙動はOffice独自の挙動であり、一般的なオブジェクト指向言語とは異なるため、「オブジェクト」という言い方でデータを持つ部品であることを示しています。
Office独自の挙動とは、VBAがOfficeアプリケーションと統合されている仕組みの動作のことを指しています。VBAの裏側ではExcelなどのOfficeアプリケーションはCOM(Component Object Model)という異なるアプリケーション間でやり取りを行う仕組みを使って、RangeなどのオブジェクトとVBAの橋渡しをしています。
VBAは公式ヘルプでも「オブジェクト」という言い方で記載されています。
3. VBA初心者への配慮
VBAの利用者は本職プログラマー以外にも想定されるため、「クラス」や「インスタンス」という抽象的な概念はオブジェクト指向を学ぶ機会がない人にとっては理解が難しいため、「実際に使うもの=オブジェクト」という言い方で理解しやすい表現にしていると考えられます。
その理由として、「Dictionaryオブジェクト」などは自分でコードにNewを書かなければならないため、「Dictionaryクラス」と「Dictionaryインスタンス」と呼ぶのが技術的には正しいのですが、そうは言わず、「Dictionaryオブジェクト」という言い方で公式ヘルプにも書いてあります。
「VBAの部品はなんもかんも”オブジェクト”」ということにしていると思われます。
New が必要なオブジェクトと不要なオブジェクトの違い
VBAでは、オブジェクトを使うときに New が必要なものと、不要なものがあります。それをコードで説明します。
なお、コード内でDictionaryを使っていますが、Dictionaryを使う場合は事前にVBA画面のツールメニュー→参照設定を選び、参照設定ダイアログで「Microsoft Scripting Runtime」にチェックを付けます。
Dictionaryの詳細については「VBAのDictionaryの使い方(全メソッドとプロパティ網羅)」をご参照ください。
■New が必要な例(自作クラス、Dictionary など)
1 2 |
Dim dict As Object Set dict = New Scripting.Dictionary |
1 2 |
Dim p As Person Set p = New Person |
これらは、Newによってクラスのインスタンスが生成され、メモリ上にオブジェクトが作成されます。
■New が不要な例(Range、Worksheet など)
1 2 |
Dim rng As Range Set rng = Worksheets("Sheet1").Range("A1") |
1 2 |
Dim sht As Worksheet Set sht = ThisWorkbook.Worksheets(1) |
これらは Excelの内部にすでに存在している実体を参照しており、RangeやWorksheetは、すでに開いているブックやシートに存在しているExcel内部のオブジェクトなので、VBAから参照する際はあらためてNewする必要がありません。
まとめ
オブジェクトを使うには、その元になるクラスが必要です。
ただし、Excelにあらかじめ存在しているRange等のオブジェクトは、Excel側が生成済みなので New を書く必要はありません。
オブジェクト種別 | Newが必要か | 理由 | 主な使用例 |
---|---|---|---|
Range, Worksheet | 不要 | Excel が既に作っており、参照するだけで使える | Worksheets(“Sheet1”).Range(“A1”) |
Scripting.Dictionary | 必要 | New で生成しないとデータを格納できない | Set dict = New Scripting.Dictionary |
自作クラス(Personなど) | 必要 | Newでインスタンス化しないと使えない | Set p = New Person |