連載

改訂版
プロフェッショナルVB.NETプログラミング

Chapter 05 オブジェクト関連の変化

株式会社ピーデー 川俣 晶
2004/04/15
Page1 Page2 Page3 Page4


 本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。

共有コンストラクタ

 クラスの中で、Sharedキーワードを付けたメンバは、インスタンスが作成されなくても存在し、インスタンスの数と関係なく実体は1つだけ存在する。このメンバを初期化するために、共有コンストラクタという機能がある。リスト5-35はそれを利用した例である(Sharedキーワードについては、インスタンスを作成せずに呼び出せるメソッドも参照)。

 1: Public Class A
 2:   Private Shared a(9) As String
 3:
 4:   Shared Sub New()
 5:     Dim i As Integer
 6:     For i = 0 To 9
 7:       a(i) = "オフ"
 8:     Next
 9:   End Sub
10:
11:   Public Shared Sub TurnOn(ByVal index As Integer)
12:     a(index) = "オン"
13:   End Sub
14:
15:   Public Shared Sub Dump()
16:     Dim i As Integer
17:     For i = 0 To 9
18:       Trace.WriteLine(a(i))
19:     Next
20:   End Sub
21: End Class
22:
23: Public Class Form1
24:   Inherits System.Windows.Forms.Form
25:
26: …Windows フォーム デザイナで生成されたコード…
27:
28:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
29:     A.TurnOn(2)
30:     A.TurnOn(5)
31:     A.TurnOn(7)
32:     A.Dump()
33:   End Sub
34: End Class
リスト5-35 共有されるメンバを初期化するために共有コンストラクタを使用したプログラム

 これを実行すると以下のようになる。

 1: オフ
 2: オフ
 3: オン
 4: オフ
 5: オフ
 6: オン
 7: オフ
 8: オン
 9: オフ
10: オフ
リスト5-36 リスト5-35の実行結果

 このソースの中で、4〜9行目が共有コンストラクタである。Sharedキーワードが共有コンストラクタであることを示している。この共有コンストラクタを呼び出すコードはどこにも記述されていない。しかし、共有されるメンバを参照する前に、自動的にこのコンストラクタは呼び出される。共有されるメンバを活用する場合には、便利な機能である。

既定のプロパティ

 VB 6では、既定のメソッドやプロパティを持つことができる。これは、インスタンスだけを指定した場合に指定されたと見なされるメソッドやプロパティのことである。例えば、フォーム上のテキストボックスに文字列を代入するときは、

TextBox1.Text = "Hello!"

のように記述するが、Textプロパティは既定のプロパティであるため、.Textを省いて、

TextBox1 = "Hello!"

と書いても等価である。

 では、実際にそういうサンプル・プログラムを記述してみよう。まず、以下のようなプロパティを持つクラス・モジュールを書いてみた。

1: Private str As String
2:
3: Public Property Get test1() As String
4:   test1 = str
5: End Property
6:
7: Public Property Let test1(s As String)
8:   str = s
9: End Property
リスト5-37 プロパティtest1を持つクラスを定義したプログラム

 次に、[ツール]メニューの[プロシージャ属性]を選んで、[詳細]ボタンを押し、名前test1に対応する[プロシージャID]を「(既定値)」に変更する。

●図5-38 VB 6の[プロシージャ属性]ダイアログ

 これで、プロパティtest1は既定のプロパティになったので、リスト5-39のようなコードを記述できるようになる。

1: Private Sub Form_Load()
2:   Dim a As New Class1
3:   a = "Hello!"
4:   Debug.Print a
5:   a.test1 = "World!"
6:   Debug.Print a.test1
7: End Sub
リスト5-39 既定のプロパティとして設定したプロパティtest1を使用したプログラム

 これを実行すると以下のようになる。

1: Hello!
2: World!
リスト5-40 リスト5-39の実行結果

 では、これに相当するプログラムがVB.NETで書けるだろうか。答えは「書けない」である。VB.NETには、既定のプロパティやメソッドは存在しないのである。なお、例外的に、引数のあるプロパティを既定のプロパティとして指定することはできる(引数を持つ既定のプロパティを参照)。

 なるべくこれに近いサンプル・プログラムを書いてみよう。まずは、クラス・モジュールから。

 1: Public Class Class1
 2:   Private str As String
 3:
 4:   Public Property test1() As String
 5:     Get
 6:       Return str
 7:     End Get
 8:     Set(ByVal Value As String)
 9:       str = Value
10:     End Set
11:   End Property
12: End Class
リスト5-41 リスト5-37をVB.NETで書き換えたプログラム

 これを呼び出すプログラムは、リスト5-42のようになる。Class1型変数への代入はエラーになるので、プロパティ名は明示的に書き込まねばならない。だが、Trace.WriteLineメソッドに渡す場合、Class1型のままでもコンパイルエラーにはならない。これは、そのまま残してみよう。

1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2:   Dim a As New Class1()
3:   a.test1 = "Hello!"
4:   Trace.WriteLine(a)
5:   a.test1 = "World!"
6:   Trace.WriteLine(a.test1)
7: End Sub
リスト5-42 リスト5-41のプロパティを使用したプログラム

 これを実行すると、以下のようになる。

1: Sample002o2.Class1
2: World!
リスト5-43 リスト5-42の実行結果

 見てのとおり、4行目のTrace.WriteLine(a)は、まったく無関係の文字列が出力されており、似ても似つかない。この文字列は名前空間を含むクラスのフルネームである。クラスは、特に設定しない限り、Trace.WriteLineメソッドの引数に渡されるとフルネームを出力する。

 さて、このとき出力される文字列は、ある方法でカスタマイズできる。つまり、非常に限定された状況でのみ、既定のプロパティがあるかのように振る舞わせることができる。リスト5-44はそれを実際に試してみた例である。

 そのためには、クラス・モジュールにToStringというメソッドを追加する。

 1: Public Class Class1
 2:   Private str As String
 3:
 4:   Public Property test1() As String
 5:     Get
 6:       Return str
 7:     End Get
 8:     Set(ByVal Value As String)
 9:       str = Value
10:     End Set
11:   End Property
12:
13:   Public Overrides Function ToString() As String
14:     ToString = str
15:   End Function
16: End Class
リスト5-44 既定のプロパティがあるかのように振る舞わせたプログラム

 呼び出す側のコードの変更はない(リスト5-42と同じ)。これを実行すると以下のようになる。

1: Hello!
2: World!
リスト5-45 リスト5-44の実行結果

 ここでポイントになるのは、ToStringメソッドである。コード13行目を見て分かるとおり、Overridesキーワードを使って、ToStringメソッドの内容を入れ替えている(Overridesキーワードについては、Overridesキーワードを使って継承時にメソッドの動作を入れ替えるを参照)。だが、このコードにToStringメソッドは1回しか出現しない。内容を入れ替えるなら、2回以上ToStringメソッドの定義がなければならないし、さらに使われているのなら、コードのどこかにToStringメソッドの呼び出しがなければならない。これはどうしたことだろうか?

 まず、すべてのクラスは暗黙的にSystem.Objectというクラスを継承しているという事実がある。そして、System.Objectには、ToStringというメソッドが含まれている。このメソッドを置き換えるコードが、このコードの13〜15行目というわけである。そして、第2のポイントは、Trace.WriteLineメソッドは、引数の値を出力可能な文字列に変換するために、このToStringメソッドを呼び出すことである。つまり、クラスのToStringメソッドを記述すれば、Trace.WriteLineメソッドで出力される内容を自由にコントロール可能というわけである。そのほか、ToStringメソッドは、あらゆるオブジェクトを文字列に変換するために利用される定番のメソッドであるため、これを実装しておく価値は大きい。しかし、これは既定のプロパティとはまったく別個の機能であることに注意が必要である。


 INDEX
  [連載] 改訂版 プロフェッショナルVB.NETプログラミング
  Chapter 05 オブジェクト関連の変化
    1.オブジェクト生成と解放のタイミングの違い/オーバーロード/コンストラクタへの引数
    2.インターフェイス機能の変更点/プロパティ構文の変更/インスタンスを作成せずに呼び出せるメソッド
  3.共有コンストラクタ/既定のプロパティ
    4.引数を持つ既定のプロパティ/Disposeパターン/Instancingプロパティの変更
 
「改訂版 プロフェッショナルVB.NETプログラミング 」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH