Visual Basic のオブジェクトとクラス

オブジェクトとは、1 つの単位として扱うことのできるコードとデータの組み合わせです。オブジェクトは、コントロールやフォームのようなアプリケーションの一部である場合もあります。また、アプリケーション全体が 1 つのオブジェクトである場合もあります。

Visual Basic でアプリケーションを作成する場合、作業では常にオブジェクトを使用します。コントロール、フォーム、データ アクセス オブジェクトなど、Visual Basic に用意されたオブジェクトを使用できます。また、Visual Basic アプリケーション内の、他のアプリエーションのオブジェクトも使用できます。さらに、独自のオブジェクトを作成し、作成したオブジェクトにプロパティやメソッドを追加することも可能です。オブジェクトは、プログラムの既成部品として機能します。オブジェクトを使うと、一度記述したコードを繰り返し再利用できます。

このトピックでは、オブジェクトの詳細について説明します。

クラスとオブジェクト

Visual Basic の各オブジェクトは、クラスによって定義されます。クラスによって、オブジェクトの変数、プロパティ、プロシージャ、およびイベントが説明されます。オブジェクトは、クラスのインスタンスです。クラスを定義すると、必要なだけオブジェクトを作成できます。

オブジェクトとクラスの関係は、クッキーとクッキーの抜き型にたとえることができます。クッキーの抜き型はクラスです。抜き型は、大きさや形など、それぞれのクッキーの特徴を定義します。このクラスを基にオブジェクトを作成します。このオブジェクトに相当するのがクッキーです。

メンバーにアクセスする前に、オブジェクトを作成する必要があります。

クラスからオブジェクトを作成するには

  1. オブジェクトの作成元のクラスを決定します。

  2. Dim ステートメント (Visual Basic) を記述して、クラス インスタンスを代入する変数を作成します。変数の型は、目的のクラスの型にする必要があります。

    Dim nextCustomer As customer 
    
  3. New 演算子 (Visual Basic) キーワードを追加して、変数をそのクラスの新しいインスタンスに初期化します。

    Dim nextCustomer As New customer
    
  4. これで、オブジェクト変数を介してそのクラスのメンバーにアクセスできます。

    nextCustomer.accountNumber = lastAccountNumber + 1
    

[!メモ]

可能な限り、変数は代入するクラスの型を使用して宣言してください。これは、事前バインディングと呼ばれます。コンパイル時にクラス型がわからない場合は、変数を オブジェクト型 (Object) で宣言しておき、遅延バインディングを行うことで対応できます。ただし、遅延バインディングではパフォーマンスが遅くなり、また、ランタイム オブジェクトのメンバーに対するアクセスが制限されます。詳細については、「オブジェクト変数の宣言 (Visual Basic)」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gif複数のインスタンス

クラスから新しく作成されたオブジェクトは、互いに同一であることがよくあります。ただし、個々のオブジェクトとして存在した後は、他のインスタンスと関係なく、変数およびプロパティを変更できます。たとえば、フォームに 3 つのチェック ボックスを追加した場合、各チェック ボックスのオブジェクトは CheckBox クラスのインスタンスです。各 CheckBox オブジェクトは、クラスで定義されている同じ特性や機能 (プロパティ、変数、プロシージャ、およびイベント) を共有します。その一方で、各オブジェクトはそれぞれ固有の名前を持ち、個別に有効または無効にしたり、フォーム上の異なる場所に配置したりできます。

オブジェクト メンバー

オブジェクトは、アプリケーションの要素であり、クラスのインスタンスです。フィールド、プロパティ、メソッド、およびイベントは、オブジェクトの構成要素であり、オブジェクトのメンバーを構成します。

527aztek.collapse_all(ja-jp,VS.110).gifメンバー アクセス

オブジェクト変数の名前、ピリオド (.)、およびメンバーの名前の順で指定して、オブジェクトのメンバーにアクセスします。Label オブジェクトの Text プロパティを設定する例を次に示します。

warningLabel.Text = "Data not saved"

527aztek.collapse_all(ja-jp,VS.110).gifメンバーを一覧表示する IntelliSense

[メンバーの一覧] オプションを起動すると、たとえば、メンバー アクセス演算子としてピリオド (.) を入力したときに、IntelliSense によってクラスのメンバーが一覧表示されます。クラスのインスタンスとして宣言された変数の名前の後にピリオドを入力した場合、IntelliSense によってすべてのインスタンス メンバーが一覧表示されますが、共有メンバーは表示されません。クラス名自体の後にピリオドを入力した場合、IntelliSense によってすべての共有メンバーが一覧表示されますが、インスタンス メンバーは表示されません。詳細については、「IntelliSense の使用方法」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gifフィールドとプロパティ

プロパティとフィールドは、オブジェクトに格納されている情報を表します。プロシージャでローカル変数を取得および設定する場合と同じ方法で、代入ステートメントを使用して値を取得および設定します。Label オブジェクトの Width プロパティを取得し、ForeColor プロパティを設定する例を次に示します。

Dim warningWidth As Integer = warningLabel.Width
warningLabel.ForeColor = System.Drawing.Color.Red

フィールドもメンバー変数と呼ばれます。

次の場合はプロパティ プロシージャを使用します。

  • 値を設定または取得する時期と方法を制御する必要がある場合。

  • プロパティに評価する必要のある明確な値のセットがある場合。

  • 値の設定により、IsVisible のプロパティなど、オブジェクトの状態が大きく変化する場合。

  • プロパティの設定により、他の内部変数が変更されたり、他のプロパティの値が変更される場合。

  • プロパティを設定または取得する前に、一連の手順を実行する必要がある場合。

次の場合はフィールドを使用します。

  • 自己検証型の値である場合。たとえば、True や False 以外の値を Boolean 変数に代入すると、エラーが発生するか、データ変換が自動的に実行されます。

  • データ型でサポートされる範囲にある値がすべて有効である場合。Single 型または Double 型のプロパティの多くがこれに当てはまります。

  • プロパティが String データ型であり、文字列のサイズや値に制限がない場合。

  • 詳細については、「Property プロシージャ (Visual Basic)」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gifメソッド

メソッドは、オブジェクトが実行できる処理です。たとえば、Add は、コンボ ボックスに新しいエントリを追加する、ComboBox オブジェクトのメソッドです。

Timer オブジェクトの Start メソッドの例を次に示します。

Dim safetyTimer As New System.Windows.Forms.Timer
safetyTimer.Start()

メソッドとは、オブジェクトによって公開されるプロシージャです。

詳細については、「Visual Basic におけるプロシージャ」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gifイベント

イベントとは、オブジェクトによって認識されるアクション (マウス クリックやキー入力など) であり、それに応答するためのコードを記述できます。イベントは、ユーザーによる操作やプログラム コードの結果として発生する場合と、システムによって発生する場合があります。イベントを通知するコードの場合はイベントを発生させると言い、それに応答するコードの場合は処理すると言います。

オブジェクトが発生させるカスタム イベントを独自に作成し、他のオブジェクトに処理させることもできます。詳細については、「イベント (Visual Basic)」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gifインスタンス メンバーおよび共有メンバー

クラスからオブジェクトを作成するとき、結果はそのクラスのインスタンスになります。Shared (Visual Basic) キーワードを使用して宣言されていないメンバーは、厳密な意味で特定のインスタンスに属しているインスタンス メンバーです。あるインスタンスのインスタンス メンバーは、同じクラスの他のインスタンスにある同じメンバーとは無関係です。たとえば、インスタンス メンバー変数は異なるインスタンスで異なる値を持つことができます。

Shared キーワードを使用して宣言されたメンバーは、特定のインスタンスにではなく、クラス全体に属している共有メンバーです。作成したクラスのインスタンスの数にかかわらず、またインスタンスを作成していない場合でも、共有メンバーは 1 つだけ存在します。たとえば、共有メンバー変数は、クラスにアクセスできるすべてのコードが利用できる値を 1 つだけ持っています。

527aztek.collapse_all(ja-jp,VS.110).gif非共有メンバーへのアクセス

オブジェクトの非共有メンバーにアクセスするには

  1. オブジェクトがそのクラスから作成され、オブジェクト変数に割り当てられていることを確認してください。

    Dim secondForm As New System.Windows.Forms.Form
    
  2. メンバーにアクセスするためのステートメントで、オブジェクト変数名の後にメンバー アクセス演算子 (.)、次にメンバー名を続けて記述します。

    secondForm.Show()
    

527aztek.collapse_all(ja-jp,VS.110).gif共有メンバーへのアクセス

オブジェクトの共有メンバーにアクセスするには

  • クラス名の後にメンバー アクセス演算子 (.)、次にメンバー名を続けて記述します。常にクラス名を使用して、オブジェクトの Shared メンバーに直接アクセスする必要があります。

    MsgBox("This computer is called " & Environment.MachineName)
    
  • 既にクラスからオブジェクトを作成してある場合、オブジェクト変数を使用して、Shared メンバーにアクセスすることもできます。

527aztek.collapse_all(ja-jp,VS.110).gifクラスとモジュールの違い

クラスとモジュールの主な違いは、クラスはオブジェクトとしてインスタンス化でき、標準モジュールはインスタンス化できないことです。標準モジュールのデータには 1 つのコピーしか存在しません。したがって、プログラムのある部分で標準モジュールのパブリック変数を変更した後、プログラムの別の部分で同じ変数を読み取ると、変更後の値が取得されます。一方、オブジェクト データは、オブジェクトのインスタンスごとに存在します。また、標準モジュールとは異なり、クラスはインターフェイスを実装できます。

[!メモ]

Shared 修飾子をクラス メンバーに適用すると、そのクラス メンバーは、クラスの特定のインスタンスではなくクラス自身に関連付けられます。そのメンバーに対しては、モジュール メンバーにアクセスするのと同じ方法で、クラス名によって直接アクセスできます。

クラスとモジュールでは、メンバーに使用されるスコープも異なります。クラス内で定義されたメンバーは、クラスの特定のインスタンス内がスコープとなり、そのオブジェクトの有効期間にだけ存在します。クラスの外側からクラス メンバーにアクセスするには、Object.Member の形式の完全修飾名を使用する必要があります。

一方、モジュール内で宣言したメンバーは既定でパブリック アクセスとなり、そのモジュールにアクセスできる任意のコードからアクセスできます。つまり、標準モジュールの変数は、プロジェクトのどこからでも参照でき、プログラムが実行されている間ずっと存在するため、事実上のグローバル変数です。

クラスとオブジェクトの再利用

オブジェクトを使うと、一度宣言した変数やプロシージャをいつでも必要なときに再利用できます。たとえば、アプリケーションにスペル チェック機能を追加する場合は、スペル チェック機能に必要なすべての変数やサポート関数を定義することになります。スペル チェック プログラムをクラスとして作成すると、コンパイル済みアセンブリへの参照を追加するだけで、このスペル チェック プログラムを他のアプリケーションで再利用できるようになります。さらに、既に他の人によって開発されたスペル チェック クラスを使うと、その分の開発の手間を省くことができます。

.NET Framework には、利用可能なコンポーネントの例が数多くあります。次の例では、System 名前空間の TimeZone クラスを使用しています。TimeZone には、現在のコンピューター システムのタイム ゾーンに関する情報を取得できるメンバーがあります。

Public Sub examineTimeZone()
    Dim tz As System.TimeZone = System.TimeZone.CurrentTimeZone
    Dim s As String = "Current time zone is "
    s &= CStr(tz.GetUtcOffset(Now).Hours) & " hours and "
    s &= CStr(tz.GetUtcOffset(Now).Minutes) & " minutes "
    s &= "different from UTC (coordinated universal time)"
    s &= vbCrLf & "and is currently "
    If tz.IsDaylightSavingTime(Now) = False Then s &= "not "
    s &= "on ""summer time""."
    MsgBox(s)
End Sub

この例では、最初の Dim ステートメント (Visual Basic) で、TimeZone 型のオブジェクト変数を宣言し、これを CurrentTimeZone プロパティで返される TimeZone オブジェクトに割り当てています。

オブジェクト間の関係

オブジェクトを互いに関連付ける方法はいくつかあります。主な関係として階層とコンテインメントがあります。

527aztek.collapse_all(ja-jp,VS.110).gif階層関係

より基本的なクラスから別のクラスが派生している場合、これらのクラスの間には階層関係があるといいます。クラスの階層構造は、より一般的なクラスの内部処理形式である項目を記述する時に便利です。

次の例では、通常の Button のように動作し、前景色と背景色とを反転させるメソッドを公開する、特殊な Button を定義します。

既存のクラスの派生クラスを定義するには

  1. Class ステートメント (Visual Basic) を使用して、必要なオブジェクトの作成元となるクラスを定義します。

    Public Class reversibleButton

    クラスの最後のコード行の後には、必ず End Class ステートメントを指定してください。既定では、Class ステートメントを入力したときに、統合開発環境 (IDE: Integrated Development Environment) によって自動的に End Class が挿入されます。

  2. Class ステートメントの直後に Inherits ステートメント を指定します。新しいクラスの派生元のクラスを指定します。

    Inherits System.Windows.Forms.Button

    新しいクラスには、基本クラスで定義されているすべてのメンバーが継承されます。

  3. 派生クラスで公開する追加のメンバー用のコードを追加します。たとえば、reverseColors メソッドを追加する場合、派生クラスは次のようになります。

    Public Class reversibleButton
        Inherits System.Windows.Forms.Button
        Public Sub reverseColors() 
            Dim saveColor As System.Drawing.Color = Me.BackColor
            Me.BackColor = Me.ForeColor
            Me.ForeColor = saveColor
        End Sub
    End Class 
    

    この reversibleButton クラスのオブジェクトを作成すると、作成したオブジェクトでは、Button クラスのすべてのメンバーに加え、reversibleButton で定義した reverseColors メソッドなどの新しいメンバーにアクセスできます。

派生クラスは、派生元のクラスからメンバーを継承するため、クラスの階層構造のレベルが深くなるにつれてより複雑なクラスを作成できます。詳細については、「継承の基本 (Visual Basic)」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gifコードのコンパイル

コンパイラでは、新規クラスの派生元とするクラスにアクセスできる必要があります。このためには、上の例で示したように名前を完全に修飾することや、Imports ステートメント (.NET 名前空間および型) で名前空間を指定することが必要になる場合があります。クラスが別のプロジェクト内にある場合は、そのプロジェクトへの参照を追加することも必要になる場合があります。詳細については、「プロジェクト参照の管理」を参照してください。

527aztek.collapse_all(ja-jp,VS.110).gifコンテインメント関係

オブジェクト間の別の関係として、コンテインメント関係があります。コンテナー オブジェクトとは、論理的に他のオブジェクトをカプセル化するオブジェクトです。たとえば、OperatingSystem オブジェクトは論理的に Version オブジェクト (Version プロパティによって返される) を含んでいます。コンテナー オブジェクトが物理的に他のオブジェクトを含んでいるわけではないことに注意してください。

527aztek.collapse_all(ja-jp,VS.110).gifコレクション

オブジェクトの実際のコンテインメントを表すものの 1 つがコレクションです。コレクションは、列挙できる、類似したオブジェクトのグループです。Visual Basic の For Each...Next ステートメント (Visual Basic) には、コレクションの項目を反復処理するための特別な構文があります。さらに、コレクションでは、多くの場合、Item を使って、インデックスや関連付けた一意の文字列で要素を取得できます。コレクションは、インデックスを使わずに項目を追加したり削除したりできるため、配列よりも使い方が簡単です。使い方が簡単なため、フォームやコントロールの格納によく使われます。

関連トピック