クラスとは、簡単に言うと構造体のようにいくつかのデータを持ち、それらのデータに対して処理を行う手続き(メソッドもしくはプロシージャ)も合わせ持つ複合データ型です。 ここで言うクラス(Class)は「学級・教室」などの意味ではなく、「種類・分類・階級」の意味の方を表します。
VB.NETにおけるクラス
VB.NETにおけるクラスは多くの部分で構造体と類似していますが、両者の違いをまとめると次のようになります。
- クラスは参照型であり、構造体は値型である (値型と参照型)
- クラスはファイナライザ(デストラクタ)を実装できるが、構造体はできない (オブジェクトの破棄)
- クラスは継承を行うことができるが、構造体はできない
このような特徴はVB.NETに固有のものではなく、C#など他の.NET Frameworkの言語とも共通するものとなっています。
クラスの宣言
一つのcls
ファイルに一つのクラスを記述していたVB6以前とは異なり、VB.NETではClass
キーワードを使ってクラス宣言します。 宣言の例は次の通りです。
' Accountクラスの宣言
Class Account
' IDを格納するフィールド
Public ID As Integer
' 名前を格納するフィールド
Public Name As String
End Class
クラスの宣言はClass
キーワードを用いて宣言し、End Class
までがクラス宣言になります。 その間でフィールド(メンバ変数)、プロパティ、メソッドなどを宣言します。 フィールドなどクラスのメンバにはPublic
などのアクセシビリティを指定することができます。
また、構造体やモジュールと同様に、クラスも一つのファイルに任意個のクラスを宣言することができます。 クラスと構造体を一つのファイルでまとめて宣言することもできます。
' クラスC1の宣言
Class C1
End Class
' クラスC2の宣言
Class C2
End Class
' 構造体S1の宣言
Structure S1
End Structure
インスタンス
構造体とは異なり、クラスはクラス型変数を宣言しただけでは使用できません。 インスタンスを作成して宣言した変数に代入することで初めてクラスを使えるようになります。
Classキーワードによって宣言したクラスはただの定義であり、それを実体化したものがインスタンスであり、インスタンスを作成することを「クラスをインスタンス化する」といいます。 クラスとは設計図であり、インスタンスとはその設計図を元に作られた個々の製品であるとイメージすればわかりやすいかもしれません。
クラスとクラス型変数、インスタンスの関係を次のコードを使って説明します。
Imports System
' クラス(宣言)
Class Account
Public ID As Integer
Public Name As String
End Class
Module Sample
Sub Main()
Dim alice As Account ' クラス型変数
alice.ID = 1
alice.Name = "Alice"
End Sub
End Module
このコードの概要を説明すると、まずIDとNameという二つのフィールドを持ったAccountクラスが宣言されています。 そして、このクラス型の変数alice
をMainプロシージャで宣言しています。 さらに、宣言した変数alice
に対して、IDフィールドとNameフィールドにそれぞれ値を割り当てています。
このコードは一見動作するように見えるかもしれませんが、実際にはIDフィールドに値を設定しようとした時点で次のような例外エラーが発生します。
ハンドルされていない例外 : System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。 at Sample.Main() in E:\sample.vb:line 12
このエラーメッセージは、変数alice
にはインスタンスへの参照が設定されていないために、IDフィールドを設定する対象のインスタンスが無いことが原因で発生しています。 このように、具体的なインスタンスを格納していない場合クラス変数には初期値としてNothingが代入されているため、そのような変数を使ってインスタンスに対して操作を行おうとすると例外NullReferenceExceptionがスローされます。
クラスはインスタンス化することで使用できるようになります。 インスタンスの作成にはNew
キーワードを使用します。 先ほどの例とは異なり、次のコードは問題なく動作します。
Imports System
Class Account
Public ID As Integer
Public Name As String
End Class
Module Sample
Sub Main()
Dim alice As Account
' 新たにAccountクラスのインスタンスを作成し、変数aliceへ代入
alice = New Account()
' 作成したインスタンスに対して操作を行う
alice.ID = 1
alice.Name = "Alice"
End Sub
End Module
次のように、変数の宣言およびインスタンスの作成と変数への代入を一行で記述することもできます。
' 変数aliceを宣言し、Accountクラスのインスタンスを作成して代入する
Dim alice As Account = New Account()
alice.ID = 1
alice.Name = "Alice"
これをさらに簡略化した次のような構文もサポートされています。 どちらも同じ結果となりますが、一般的にはこの形式が多く使われているようです。
' 変数aliceを宣言し、Accountクラスのインスタンスを作成して代入する
Dim alice As New Account()
alice.ID = 1
alice.Name = "Alice"
インスタンスのフィールドに値が代入されているかを確認すると次のようになります。
Imports System
Class Account
Public ID As Integer
Public Name As String
End Class
Module Sample
Sub Main()
' 変数aliceを宣言し、Accountクラスのインスタンスを作成して代入する
Dim alice As New Account()
alice.ID = 1
alice.Name = "Alice"
Console.WriteLine("ID = {0}, Name = {1}", alice.ID, alice.Name)
End Sub
End Module
ID = 1, Name = Alice
構造体との共通点
クラスと構造体は機能的にはさまざまな点が共通しています。 メソッド、プロパティ、コンストラクタなどの要素は構造体の場合とほとんど変わりません。 クラスでは構造体と異なり引数を取らないコンストラクタを作成できるようになっています。
Imports System
Class Account
' 内部的にIDを保持するためのフィールド
Private _ID As Integer
' 内部的に名前を保持するためのフィールド
Private _Name As String
' Newという名前のメソッドはコンストラクタとして扱われる
Public Sub New(ByVal id As Integer, ByVal name As String)
_ID = id
_Name = name
End Sub
' クラスでは引数を取らないコンストラクタを作成することができる
Public Sub New()
_ID = 0
_Name = "(default)"
End Sub
' 次のような宣言により、クラスにプロパティを持たせることもできる
Public Property ID() As Integer
Get
' プロパティを介して返される値を返す
Return _ID
End Get
Set(ByVal Value As Integer)
' プロパティを介して設定される値を保持する
_ID = Value
End Set
End Property
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal Value As String)
_Name = Value
End Set
End Property
' メソッドを持たせることができるほか、基底クラスのメソッドを
' オーバーライドして動作を変えることもできる
Public Overrides Function ToString() As String
Return "ID = " + _ID.ToString() + ", Name = " + _Name
End Function
End Class
Module Sample
Sub Main()
' コンストラクタにパラメータを指定しないでインスタンスを作成する
Dim alice As New Account()
' プロパティの値を変更する
alice.ID = 1
alice.Name = "Alice"
' コンストラクタにパラメータを指定してインスタンスを作成する
Dim bob As New Account(2, "Bob")
' コンストラクタにパラメータを指定してインスタンスを作成する
Dim charlie As New Account(3, "Charlie")
' プロパティの値を変更する
charlie.ID = 999
' ToStringメソッドを呼び出して文字列化して表示する
Console.WriteLine(alice.ToString())
Console.WriteLine(bob.ToString())
' Console.WriteLineは自動的にToStringを呼び出して文字列化することもできるので
' このようにしても同じ
Console.WriteLine(charlie)
End Sub
End Module
ID = 1, Name = Alice ID = 2, Name = Bob ID = 999, Name = Charlie
参照型と値型
クラスと構造体の違いの一つに、値型であるか参照型であるかという違いがあります。 クラスは参照型で、構造体は値型です。
値型の変数は常にインスタンスを持ち、その値に対して直接アクセスするのに対して、参照型の変数ではインスタンスへの参照を通してインスタンスにアクセスします。 また、値型の変数に対して代入を行うとその値がコピーされるのに対して、参照型の変数に対して代入を行うと参照のみが代入され、実際のインスタンスはコピーされません。
この違いを明確にするコードを使って解説します。
Imports System
' クラス(参照型)で実装した型
Class RefAccount
Public Name As String
End Class
Module Sample
Sub Main()
' クラス(参照型)のインスタンスを作成
Dim a1 As New RefAccount
Dim a2 As New RefAccount
a1.Name = "Alice"
a2.Name = "Bob"
' それぞれのNameフィールドの値を表示
Console.WriteLine("{0} {1}", a1.Name, a2.Name)
' a1が参照しているインスタンスへの参照がa2に代入される
a2 = a1
' a2.Nameの値を変更
a2.Name = "Charlie"
' それぞれのNameフィールドの値を再度表示
Console.WriteLine("{0} {1}", a1.Name, a2.Name)
End Sub
End Module
Alice Bob Charlie Charlie
Imports System
' 構造体(値型)で実装した型
Structure ValAccount
Public Name As String
End Structure
Module Sample
Sub Main()
' 構造体(値型)のインスタンスを作成
Dim a1 As New ValAccount
Dim a2 As New ValAccount
a1.Name = "Alice"
a2.Name = "Bob"
' それぞれのNameフィールドの値を表示
Console.WriteLine("{0} {1}", a1.Name, a2.Name)
' a1のコピーがa2に代入される
a2 = a1
' a2.Nameの値を変更
a2.Name = "Charlie"
' それぞれのNameフィールドの値を再度表示
Console.WriteLine("{0} {1}", a1.Name, a2.Name)
End Sub
End Module
Alice Bob Alice Charlie
この二つのコードにはクラスを使っているか構造体を使っているかの違いしかありませんが、実行結果の違い、参照型では代入後のa2
に対する変更がa1
にも影響している点に注目してください。
構造体(値型)では、代入によって代入元変数a1
のコピーが作成され代入先a2
に設定されるため、代入先と代入元はどちらも違うインスタンスとなります。 一方クラス(参照型)では、代入によって代入元変数a1
が参照しているインスタンスへの参照が代入先a2
に設定されるため、代入先と代入元はどちらも同じインスタンスを参照することになります。 このため、クラスの場合では代入によってa1
とa2
には同じインスタンスへの参照が設定されるため、a2
に対する変更はa1
に対して変更することと同じとなり、実行結果にあるようにどちらも同じ値が表示されることになります。
このように、クラスと構造体はどちらも同じような機能を持っていますが、一方で値型と参照型という明確な動作の違いもあります。 どちらを選ぶかによってパフォーマンスが大きくことなることもあるほか、List(Of T)で構造体のフィールド・プロパティを変更する場合のようにがわかりづらい問題が発生することもあるので、安易な判断を行わず両者の違いをよく理解して使い分ける必要があります。
共有メンバ
クラスのフィールド・プロパティ・メソッドなどすべてのメンバはインスタンスを作成することで初めて使用できるようになります。 一方、Shared
キーワードによってメンバを共有メンバにすると、全インスタンスに共通したメンバ(各インスタンスではなく直接クラスに属するメンバ)となり、インスタンスを作成せず使用できるようになります。 クラス外から共有メンバを参照する場合は、クラス名.メンバ名のように記述します。
Imports System
Class Account
' 共有メンバ
Private Shared Count As Integer = 0
' 非共有(インスタンス)メンバ
Public ID As Integer
Public Name As String
Public Sub New()
' インスタンスが作成される度にCountをカウントアップする
Count += 1
End Sub
' 共有メソッド
Public Shared Sub PrintCount()
Console.WriteLine(Count)
End Sub
End Class
Module Sample
Sub Main()
' インスタンスを3つ作成する
Dim alice As New Account()
Dim bob As New Account()
Dim charlie As New Account()
' インスタンスメンバの変更
alice.ID = 1
alice.Name = "Alice"
' 共有メソッドを呼び出して作成されたインスタンスの数を表示する
Account.PrintCount()
End Sub
End Module
3
アプリケーションのエントリポイントであるMain
メソッドをクラス内で宣言する場合もShared
で宣言します。 エントリポイントが呼び出される前にインスタンスを作成することはできないため、インスタンスを作成せずにMain
メソッドを呼び出せるようShared
を付ける必要があります。
Imports System
Class Sample
' アプリケーションのエントリポイント
Shared Sub Main()
Console.WriteLine("Hello, world!")
End Sub
End Class
インスタンスを作成せずにメソッド呼び出しや変数の参照ができるモジュールは、すべてのメンバがShared
(共有メンバ)となったクラスと見ることもできます。 一方、クラス自体にSharedキーワードを設定することはできないため、VBのクラスではC#の静的クラスに相当するものを作成することはできません。 VBではモジュールを使うことにより静的クラスに相当する機能を得ることができます。
インスタンスの破棄
New
によって作成したインスタンスはガベージコレクタによって管理され、不要と判断された時点で自動的に破棄されるため、基本的にインスタンス自体を明示的に破棄する必要はなく、また解放処理を記述する必要もありません。
Imports System
Class Account
Public Name As String
End Class
Module Sample
Sub Main()
' コンストラクタにパラメータを指定しないでインスタンスを作成する
Dim alice As New Account()
' インスタンスを使った処理
alice.Name = "Alice"
' :
' :
' :
' インスタンスが不要になっても明示的に破棄する必要はない
End Sub
End Module
しかし、インスタンスがアンマネージリソースなどガベージコレクタによる管理の対象外となるリソースを作成・使用している場合は、それを確実に解放する必要があります。 ガベージコレクタの管理対象外となるリソースを扱うクラスを作成する場合は、IDisposableインターフェイスを実装して明示的にリソースを解放できる手段を用意するしておくことが推奨されます。 また、そのようなクラスのインスタンスを使用する際においてはUsing
ステートメントを使うようにし、インスタンスを使用しおわった時点で確実に解放処理を呼び出させるようにします。
Imports System
' 明示的な解放が必要になるリソースを扱うクラス
Class Resource
' IDisposableインターフェイスを実装する
Implements IDisposable
Public Sub Dispose() Implements IDisposable.Dispose
' リソースの解放処理を記述する
End Sub
End Class
Module Sample
Sub Main()
' Usingステートメント内でインスタンスを作成・使用することにより、
' Disposeメソッドによる解放処理が確実に実行されるようにする
Using res As New Resource()
' リソースを使った処理
End Using
End Sub
End Module
次のようにFinalize
メソッドをオーバーライドすることによりデストラクタを記述することもできますが、このメソッドを明示的に呼び出すことはできません。 デストラクタはガベージコレクタによって呼び出されます。 IDisposable
を実装するクラスでは、確実に1度はDispose
メソッドが呼び出されるようにデストラクタを記述することはありますが、それ以外の多くの場合ではデストラクタを実装する必要はありません。
Imports System
Class Resource
Protected Overrides Sub Finalize()
' Finalizeメソッドをオーバーライドしてデストラクタを記述する場合は、
' 基底クラスのFinalizeメソッドも呼び出す必要がある
MyBase.Finalize()
End Sub
End Class
Module Sample
Sub Main()
Dim res As New Resource()
' このようにして直接デストラクタを呼び出すことはできない
res.Finalize()
End Sub
End Module
インターフェイスの実装については後述します。
IDisposableインターフェイスとリソースの解放、デストラクタの適切な実装についてはオブジェクトの破棄で詳しく解説しています。
インスタンスの保存・復元
.NET Frameworkでは、シリアライズによってインスタンスの状態を保存・復元することができます。 シリアライズを行うことにより、インスタンスをバイナリ形式やXML形式でファイルに保存したり、ネットワークを経由して送受信したりすることができます。 シリアライズによるインスタンスの保存・復元では、クラスごとに保存・読み込み処理を記述する必要はなく、また属性を付与することによって保存・復元時の動作を簡単にカスタマイズすることもできます。
シリアライズについてはシリアライズの基本で詳しく解説しています。
継承
VBではクラスの継承を行うことができます。 継承はクラスのみでサポートされる機能で、構造体は継承を行うことはできません。 また、VBでは多重継承を行うことはできません。
クラスの継承
クラスを継承して派生クラスを作成するには、Inherits
キーワードを使用します。 VBでは多重継承はサポートされないため、Inherits
の後ろには常に基底クラスを一つだけ指定します。
Imports System
' 基底クラス
Class Base
Sub Print()
Console.WriteLine("Base")
End Sub
End Class
' 派生クラス
Class Derived
Inherits Base ' Baseクラスを継承
End Class
Module Sample
Sub Main()
Dim d As New Derived()
d.Print()
End Sub
End Module
Base
Inherits
によって別のクラスを継承しているクラスを基底クラスとして更に継承を重ねることもできます。
オーバーライド
派生クラスで基底クラスのメソッドをオーバーライドする場合は、Overrides
キーワードを使用します。 ただし、オーバーライドする場合はオーバーライドを許可することをあらわすOverridable
キーワードが基底クラスのメソッドに付与されている必要があります。 Overridable
キーワードが付与されているメソッドは仮想メソッドとなります。 Overrides
キーワードが付与されているメソッドは暗黙的にOverridable
となるため、Overrides Overridable
のようにこれらのキーワードを記述する必要はありません。
Imports System
' 基底クラス
Class Base
' オーバーライド可能なメソッド
Overridable Sub Print()
Console.WriteLine("Base")
End Sub
End Class
' 派生クラス
Class Derived
Inherits Base
' 基底クラスのPrintメソッドをオーバーライドして動作を変える
Overrides Sub Print()
Console.WriteLine("Derived")
End Sub
End Class
Module Sample
Sub Main()
Dim d As New Derived()
d.Print()
End Sub
End Module
Derived
抽象メソッド・抽象クラス
メソッドを抽象メソッドとする場合は、Overridable
の代わりにMustOverride
キーワードを指定します。 抽象メソッドを宣言する場合はメソッドの実装とEnd Sub
の記述を省略します。 またMustOverride
が付与されたメンバを含むクラスでは、そのクラスが抽象クラスであることを表すMustInherit
キーワードをクラス宣言に付与する必要があります。 抽象クラスの継承と抽象メソッドのオーバーライドは通常のクラス・仮想メソッドの場合と同様です。
Imports System
' 抽象クラス
MustInherit Class Base
' 抽象メソッド
MustOverride Sub Print()
End Class
' 派生クラス
Class Derived
Inherits Base
' 抽象メソッドPrintの実装を記述する
Overrides Sub Print()
Console.WriteLine("Derived")
End Sub
End Class
Module Sample
Sub Main()
Dim d As New Derived()
d.Print()
End Sub
End Module
Derived
ここまでの例では値を返さないメソッド(Sub
プロシージャ)を使ってきましたが、値を返すメソッド(Function
プロシージャ)やプロパティ(Property
)の場合も同様にキーワードを指定することでメンバの仮想化・抽象化・オーバーライドを行うことができます。
Overrides
などのキーワードとともにPublic
やProtected
などのキーワードを組み合わせて指定することにより、メンバのアクセシビリティ(公開範囲)も設定することもできます。 これらのキーワードについては詳しくはアクセス修飾子で解説しています。
継承の禁止
クラスにNotInheritable
キーワードを付与することにより、継承を禁止してシール(sealed, 封印)されたクラスを作成することができます。 NotInheritable
が付与されているクラスを継承しようとした場合はコンパイル時にエラーとなります。
Imports System
' 継承を許可しないクラス
NotInheritable Class Base
Sub Print()
Console.WriteLine("Base")
End Sub
End Class
' 派生クラス
Class Derived
Inherits Base ' BC30299: 'Derived' をクラス 'Base' から継承できません。'Base' は 'NotInheritable' として宣言されています。
End Class
基底クラスのメンバ参照
派生クラス側から基底クラスを参照するにはMyBase
キーワードを使います。 例えば、派生クラスで基底クラスのコンストラクタを呼び出す場合は次の例のようにMyBase.New(引数リスト...)
とします。 コンストラクタで基底クラスのコンストラクタを呼び出す場合は、コンストラクタでの他の処理よりも先に呼び出すようにする必要があります。
Imports System
' 基底クラス
Class Base
Private _name As String
Sub New(ByVal name As String)
_name = name
End Sub
Sub Print()
Console.WriteLine(_name)
End Sub
End Class
' 派生クラス
Class Derived
Inherits Base
Sub New(ByVal name As String)
' コンストラクタに渡された値を基底クラスのコンストラクタに引き渡す
MyBase.New(name)
End Sub
End Class
Module Sample
Sub Main()
Dim d As New Derived("Derived")
d.Print()
End Sub
End Module
Derived
コンストラクタだけでなく、メソッド・フィールド・プロパティなどの場合も同様にMyBase
で基底クラスのメンバを参照することができます。 また、基底クラスを参照するMyBase
以外にも、インスタンス自身を表すMe
キーワード、自クラスのメンバを参照するMyClass
キーワードなどを使ってメンバの参照を行うことができます。
Me
, MyClass
, MyBase
の3つのキーワードについてはMe, MyClass, MyBaseで詳しく解説しています。
実行時の型判別
実行時にオブジェクトがあるクラスを継承しているか(型に互換性があるか)どうかを調べるにはTypeOf ... Is
を使用することができます。
Imports System
' 基底クラス
Class Base
End Class
' Baseを継承した派生クラス
Class Derived
Inherits Base
End Class
' Baseとは無関係のクラス
Class Other
End Class
Module Sample
Sub Main()
Dim d As New Derived()
Dim o As New Other()
If TypeOf d Is Base Then
Console.WriteLine("dはBaseクラスと互換性のある型です")
Else
Console.WriteLine("dはBaseクラスと互換性のない型です")
End If
If TypeOf o Is Base Then
Console.WriteLine("oはBaseクラスと互換性のある型です")
Else
Console.WriteLine("oはBaseクラスと互換性のない型です")
End If
End Sub
End Module
dはBaseクラスと互換性のある型です oはBaseクラスと互換性のない型です
TypeOf演算子・Is演算子についてはIs演算子・IsNot演算子・TypeOf演算子およびインスタンスや型が一致するか・インターフェイスやクラスから派生しているか判定するで詳しく解説しています。
インターフェイスの実装
VBではクラスにインターフェイスを実装することができます。 クラスの多重継承が許可されない代わりにインターフェイスは複数実装することができるため、インターフェイスを適切に実装することによってクラスに様々な機能を持たせることができます。
インターフェイスを実装するには、Implements
キーワードを使用してクラスの先頭で実装するインターフェイス名を指定します。 次に、インターフェイスメソッドの実装を記述します。 この際もImplements
キーワードを使用し、メソッド宣言の後ろにImplements インターフェイス名.メソッド名
といった記述を付記します。 このような実装をインターフェイスが持つメソッドの分だけ記述します。
以下の例はクラスにIDisposableインターフェイスを実装する例です。 IDisposableインターフェイスは引数なし・戻り値無しのメソッドDisposeを持っているので、これをクラス内で実装するようにします。
Imports System
Class Resource
' IDisposableインターフェイスを実装する
Implements IDisposable
' IDisposableインターフェイスのメソッドDisposeを実装する
Sub Dispose() Implements IDisposable.Dispose
' メソッド内の実装は省略
End Sub
End Class
クラスは複数のインターフェイスを実装することができます。 次の例では、二つのインターフェイスI1とI2を実装するクラスを作成しています。 次の例のように、実装しようとするインターフェイスに同名のメソッドが含まれている場合は、実装となるメソッド名を変えることにより同名のインターフェイスメソッドを別々の名前で実装することができます。
Imports System
Interface I1
Sub Method()
End Interface
Interface I2
Sub Method()
End Interface
Class C
' 二つのインターフェイスI1, I2を実装する
Implements I1, I2
' I1インターフェイスのメソッドMethodを、M1という名前のメソッドとして実装する
Sub M1() Implements I1.Method
End Sub
' I2インターフェイスのメソッドMethodを、M2という名前のメソッドとして実装する
Sub M2() Implements I2.Method
End Sub
End Class
.NET Frameworkには様々な役割を持つインターフェイスが用意されています。 代表的なものとして、オブジェクトの破棄を行う機能を提供するIDisposableインターフェイス(オブジェクトの破棄)、コレクションにFor Each
による列挙機能を持たせるIEnumerableインターフェイス(IEnumerable・IEnumerator)、オブジェクト同士の大小関係を比較する機能を提供するIComparableインターフェイス(大小関係の定義と比較)、オブジェクトをシリアライズする際の動作を制御するISerializableインターフェイス(BinaryFormatter・SoapFormatter §.シリアライズ動作の制御 (ISerializable))などがあります。 インターフェイスの具体的な実装例については、個々のドキュメントを参照してください。
入れ子
クラスでは別のクラスを入れ子にして宣言することができます。
Imports System
' 型のコンテナとなるクラス
Class C
' 入れ子になったクラス
Class NC
End Class
Sub M()
' 入れ子になったクラスのインスタンスを作成・使用する
Dim nc As New NC()
End Sub
End Class
入れ子にしたクラスにはアクセシビリティを設定できるため、クラス内でしか入れ子クラスを使用しない場合には入れ子クラスをPrivate
にするといったこともできます。 このようにクラスは型のコンテナとして機能するため、クラスだけでなく構造体・列挙体・モジュール・デリゲート・インターフェイスなどもクラス内に宣言することができます。
宣言の分割 (Partial)
VB2005以降では、Partial
キーワードを使用することによりクラスおよび構造体の宣言を分割することができます。 クラスのコードが長大になる場合や、自動生成部分と手動記述部分を分けて管理したい場合などには、Partial
キーワードを使ってクラス宣言を複数箇所に分割して全体を把握しやすくすることができます。 Partial
キーワードを使ったクラスの宣言は、個別のファイルに記述することも、同一のファイルに記述することもできます。
Imports System
' フィールド宣言のみを含むクラス宣言
Partial Class Account
Public ID As Integer
Public Name As String
End Class
Imports System
' コンストラクタとメソッドの宣言を含むクラス宣言
Partial Class Account
Public Sub New(ByVal id As Integer, ByVal name As String)
Me.ID = id
Me.Name = name
End Sub
Public Overrides Function ToString() As String
Return "ID = " + ID.ToString() + ", Name = " + Name
End Function
End Class
Module Sample
Sub Main()
Dim alice As New Account(1, "Alice")
Console.WriteLine(alice)
End Sub
End Module
ID = 1, Name = Alice
クラスライブラリ
プロジェクトを実行可能形式(.exe)ではなくライブラリ(.dll)としてビルドすることにより、クラスライブラリを作成することができます。 これにより、作成したクラスを別のプロジェクトでも使用できるようにすることができます。 また、このようにして作成したクラスライブラリはプロジェクトの参照に追加するだけで使用できるようになり、またVBだけでなくC#など.NET Frameworkの他の言語からも使用することができるようになっています。
クラスライブラリの作成方法などについてはクラスライブラリの作成で詳しく解説しています。