Visual Basic 初級講座
VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

 

Visual Basic 中学校 > 初級講座 >

第47回 プロパティの作成

いろいろなプロパティの作成方法を説明します。せっかくクラスを作ってもメソッドとプロパティの両方をうまく作らなくては使いにくいクラスになってしまいます。

概要

・プロパティは主に状態を表すときに使用する。

メソッド Sub ,Function 動作
プロパティ Property 状態
フィールド Public, Const 項目

・よくある基本的なプロパティの例

VB.NET2002対応 VB.NET2003対応 VB2005対応

Private _Age As Integer

Public
Property Age() As
Integer
    Get
        Return
_Age
    End
Get
   
Set(ByVal value As Integer)
        _Age = value
    End
Set
End Property

・読み取り専用プロパティを作成するにはReadOnlyキーワードを使用する。

・既定のプロパティを設定するにはDefaultキーワードを使用する。

・プロパティにも引数をつけることができる。

 

1.標準的なプロパティプロシージャ

 

今回は独自のプロパティを作る方法を説明します。

細かい説明をする前に標準的なプロパティの例を紹介しておきます。以下の例は年齢をあらわすAgeプロパティの作成例です。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Private _Age As Integer

Public
Property Age() As
Integer
    Get
        Return
_Age
    End
Get
   
Set(ByVal value As Integer)
        _Age = value
    End
Set
End Property

■リスト1:シンプルなプロパティプロシージャの例

このAgeプロパティは値を記録しておくだけで、他には何の機能もない極めてシンプルなプロパティです。

このコードをよく見てみると今までには登場しなかったような雰囲気が感じられます。プロパティの定義は確かに通常のコードとは少し雰囲気が違います。

たとえば、Public Property End Propertyの間にコードを記述すると言うのは今までに登場してきたIfEnd IfSubEnd Subなどと同じですので違和感はありませんが、この中がさらにGetEnd Get(読み方:Get = ゲット)とSetEnd Set(読み方:Set = セット)に分割されているのは特徴的です。

詳しいことは少し後で説明します。理解を深めるためにここでは簡単にプロパティプロシージャについて説明しておきましょう。

プロパティに対しては「読み取り」と「書き込み」という2つの動作ができなければなりませんので、1つのプロパティプロシージャの中が読み取り時に作動するGet節と書き込み時に作動するSet節に分かれているのです。この点は単に値を返すだけのメソッドと異なります。言うなればメソッドは「読み取り」のみの動作しかなく、メソッドに対して値を書き込むということはないのです。

それから、値を記録しておく必要があるのでプロパティプロシージャの外に変数を1つ用意しておく必要があります。これもメソッドの場合と異なります。 上記の例では変数_Ageがこの変数です。変数の名前は好きにつけてよいのですが、Ageプロパティでセットした値を記録する変数と言うことで関連のありそうな名前をつけておく野が一般的です。

特にプロパティ名の前にアンダーバーをつけた名前が良く使われます。

ただし、ここで書いたのはあくまでも標準的なプロパティとメソッドの話です。外部の変数に値を保存しないプロパティもありえますし、外部の変数に値を保存するメソッドもありえます。プログラマが指令すればなんでも言うことを聞くのがVBです。

 

2.プロパティとは?

 

技術的な説明の前について「プロパティ」という考え方について説明します。

プロパティとはクラスの状態とか特性・性質と言った意味を持っています。よくあるTextプロパティは表示している文字の状態を表すプロパティですし、Visibleプロパティは可視状態を表すプロパティです。

プロパティと違ってメソッドはクラスの動作を意味します。

ただし、何がプロパティで何がメソッドか決定するのはあくまでもプログラマです。たとえば、Textプロパティでさえプロパティにする必然性はないのです。仮にTextプロパティをメソッドで表現するとしたらテキストをセットするためのSetTextメソッドとテキストを取得するためのGetTextメソッドを用意することになります。

しかしながらプログラマの気分によってあるものはプロパティ、あるものはメソッドと分けられたのでは使うほうは混乱してしまいますから、メソッドやプロパティを作成しようとするプログラマは自分が作ろうとしている機能は本当にメソッドにすべきなのか、それともプロパティにすべきなのか考えてから作るようにしましょう。

以前に実際にあったことなのですが、他人が作ったクラスを使っていたときのことを紹介します。そのクラスはデータをファイルに保存するクラスで、私は試しにそのクラスを使ってプログラムしていたのですが、肝心の保存を行うメソッドが見つからないのです。ファイルに保存する機能があるクラスならきっとSaveみたいな名前のメソッドがあると思ってしまいますよね?ところがSaveメソッドがないのです。

ひょっとするとこれを作ったプログラマは少し私と感性が異なっていて保存を行うメソッドにOutputとかExportとか言うような名前を使っているのかと思い、メソッドを1つずつ見ていったのですがとうとうそれらしいメソッドは見つかりませんでした。

しかし、保存する機能はあるはずです。いろいろ探した結果なんと保存を行うにはプロパティを使用すると言うことがわかりました。よくは覚えていないのですがたしか、MyData.Action = Output のような感じでActionプロパティに出力状態を表す定数をセットすると保存を開始すると言う仕様だったのです。

これってとてもわかりにくいと思いませんか?MyData.Saveの方がどう考えてもわかりやすいですよね?これがここで私の説明したいことです。

つまり、ある機能をメソッドにするかプロパティにするかはプログラマの自由ですが、どちらにするかよく検討しないで作ると使う側から見て使いにくいクラスができてしまうのです。

プロパティは状態、メソッドは動作です。プロパティは静、メソッドは動と言ってもよいでしょう。

このことも含めてプロパティとメソッドの違いを表にまとめておきます。

  プロパティ メソッド
考え方 クラスの状態 クラスの動作
キーワード Property Sub, Function
読み取り
書き込み ×
詳細な動作のプログラム

■表1:プロパティとメソッド

 

3.フィールド

 

プロパティと似たようなものにはメソッドの他にフィールドがあります。 フィールドはクラスで宣言されている単なる変数のことです。単なる変数なので値を記録しておく以外には何の機能もありませんが、値を記録しておくだけのプロパティを作成するのであればフィールドとして作成したほうが楽な場合もあります。

ただし、フィールドとして作成していしまうとプロパティに許されている便利なVBの機能が使えなくなってしまいます。 また、フィールドもプロパティもパフォーマンス上は同等ですので、通常はフィールドではなくプロパティを使用するようにしてください。

フィールドの宣言はそのまま変数の宣言なのでクラス内で次のように記述するとこれだけでAgeフィールドが完成します。

VB6対応 VB.NET2002対応 VB.NET2003対応 VB2005対応


Public
Age As Integer
 

■リスト2:フィールドの例

フィールドは外部に公開するためにはPublicで宣言します。DimPrivateなどでの宣言は他のプロパティやメソッドから間接的にアクセスするプライベートなフィールドということでよく使いますが、外部から直接アクセスできなくなってしまいますのでプロパティの代わりに使うものとしては意味がありません。

なお、定数もフィールドになります。

プロパティとフィールドの違いを表にまとめておきます。

  プロパティ フィールド
考え方 クラスの状態 クラスの項目
キーワード Property Public (単なる変数・定数と同じ)
読み取り
書き込み
詳細な動作のプログラム ×

■表2:プロパティとフィールド

プロパティと似ているけれどもプロパティとは異なるメソッドとフィールドについて説明したことで、「プロパティ」の意味と機能がはっきりしてきたことと思います。

 

4.プロパティ作成の基本

 

ここからはいよいよ具体的な構文を交えてプロパティを作成する方法を説明します。

実際にプログラムをしながら説明の内容を確認していってください。プロジェクトを1つ作ってクラスを新しく追加してください。このクラスは何かの会員を表すクラス で、名前はMemberとします。

まずはMemberクラスに誕生日を表現するためのBirthDayプロパティを作成します。とりあえず何の機能もない空のBirthDayプロパティを作成すると次の通りとなります。これは空のプロパティプロシージャなのでまさにプロパティプロシージャの構造が シンプルに表現されています。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Public Class Member

    Public
Property BirthDay() As
Date
       
Get
           
'ここにプロパティから値を読み取る場合のコードを書く
       
End Get
       
Set(ByVal value As Date)
           
'ここにプロパティに値を書き込む場合のコードを書く
       
End Set
   
End Property

End
Class

■リスト3:クラス側のプログラム。空のプロパティを作ったところ。

この構造は読み取りと書き込みの両方ができるプロパティの場合です。読み取り専用または書き込み専用のプロパティの作り方は後で説明します。

この例ではGet節にもSet節にも何もプログラムがないので、まったく空のプロパティを作っていることになります。このBirthDayプロパティには値を保存する機能すらありません。

試しにフォーム側でこのクラスを使って次の通りにプログラムしてみてください。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim
ThisMember As New Member

    ThisMember.BirthDay = #6/27/1992#
    MsgBox(ThisMember.BirthDay)

End
Sub

■リスト4:フォーム側のプログラム。この段階では予期した通りには動作しない。

BirthDayに1992/6/27をセットしたすぐ後でBirthDayプロパティの値を表示するようにしているのですが、実行すると0:00:00が表示されます。BirthDayプロパティに値を保存する機能すらない証拠です。

値を保存する機能をプログラムする前にプロパティプロシージャをもう少しいじって実験してみます。次のように改造してください。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Public Class Member

    Public
Property BirthDay() As
Date
       
Get
           
MsgBox("BirthDayプロパティの値を読み取ろうとしました。")
        End
Get
       
Set(ByVal value As Date)
            MsgBox(
"BirthDayプロパティに値を書き込もうとしました。")
        End
Set
   
End Property

End
Class

■リスト5:クラス側のプログラム。実験の例で実際の機能はない。

これで先ほどと同じプログラムを試してみると、プロパティプロシージャのGet節とSet節がうまく呼び出されていることがわかります。

ここまで仕組みがわかれば値を保存するためにどのようにプログラムすればよいか理解できそうです。値を保存する機能を追加すると次のようになります。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Public Class Member

    Dim
_BirthDay As
Date

   
Public Property BirthDay() As Date
       
Get
            Return
_BirthDay
        End
Get
       
Set(ByVal value As Date)
            _BirthDay = value
        End
Set
   
End Property

End
Class

■リスト6:クラス側のプログラム。

ここまでの説明で、値を記録するだけのシンプルなプロパティの作成の仕方と動作の仕組みがわかっていただけたと思います。

誕生日を記録するプロパティができたところで、今度は年齢をあらわすAgeプロパティで作ってみましょう。AgeプロパティもBirthDayプロパティと同じように作成して読み書きできるようしてもいいのですが、誕生日がわかっていれば年齢も自動的に決定されるのでAgeプロパティは読み取り専用のプロパティとします。

読み取り専用のプロパティを作成するにはプロパティプロシージャの宣言にReadOnlyキーワード(読み方:ReadOnly = リードオンリー)を加えて、値を書き込むためのSet節を省きます。

Ageプロパティは次のようになります。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Public ReadOnly Property Age() As Integer
    Get
       
'例:BirthDay = 2001/06/27, Now = 2006/06/30の場合
        'intBirthDay = 20010627, intNow = 20060630
        'intNow - intBirthDay = 50003
        '50003 ÷10000 = 5.0003
        'ゆえに、この人物は5歳
       
Dim intBirthDay As Integer = CInt(BirthDay.ToString("yyyyMMdd"))
        Dim intNow As Integer = CInt(Now.ToString("yyyyMMdd"))

       
Return (intNow - intBirthDay) \ 10000

    End
Get
End Property

■リスト7:クラス側のプログラム。読み取り専用プロパティの例。

年齢を計算するロジックは今回説明するテーマではありません。コメントを参考にしてください。

プロパティプロシージャとして注目すべき点はGet節では単に変数に記録されている値を返すだけではなく、計算を行っている点です。このようにGet節、Set節ともに通常のVBのプロシージャと同様に好きなようにプログラムを実行させることができます。

ところで、あまり使用しませんがプロパティを書き込み専用にすることもできます。この場合はWriteOnlyキーワード(読み方:WriteOnly = ライトオンリー)を使用し、Get節を省きます。

 

5.プロパティの型は何でもよい

 

さて、今度は履歴書の履歴を管理する簡単なクラスを使っていろいろなタイプのプロパティを説明します。

まず、プロパティの型にはいろいろなクラスを自由に指定できることを紹介します。このことはわざわざ指摘しなくても当然のことなのですが、型を指定するときになんとなくIntegerStringなど基本的な型でなくてはいけないような気がしてしまう方も結構いらっしゃるようです。

プロパティの型にコレクションを指定するとクラスの利用者側で便利に使うことが可能です。

まずは履歴クラスのシンプルなコード例を使って考えて見ましょう。

VB.NET2002対応 VB.NET2003対応 VB2005対応

'■PersonalHistory
'''
<summary>履歴を編集・管理します。</summary>
Public Class PersonalHistory

    Private _Histories As New ArrayList

   
'■Histories
   
''' <summary>それぞれの履歴を表すコレクション</summary>
   
Public ReadOnly Property Histories() As ArrayList
       
Get
            Return
_Histories
        End
Get
   
End Property
    '■HistoryMemo
   
''' <summary>全履歴を取得します。</summary>
   
Public ReadOnly Property HistoryMemo() As String
       
Get
           
           
Dim Item As String
           
Dim Result As String = ""

            For
Each Item In _Histories
                Result &= Item & vbNewLine
           
Next

            Return
Result

        End
Get
   
End Property

End
Class

■リスト8:クラス側のプログラム。

このクラスではHistoriesプロパティの型がArrayListになっていることと、HistoriesプロパティにReadOnlyつまり読み取り専用が指定されていることに注意してください。

メモ  -  VB2005の場合はジェネリックも使用できます

上記の例はVB.NET2002, VB.NET2003, VB2005のどれにも当てはまります。VB2005の場合はArrayListではなくジェネリックを使用してコレクションの型を指定することができるので利用した方が良いでしょう。

ジェネリックを使用するにはArrayListの箇所をすべてList(Of String)に訂正します。

 

このクラスの利用例を以下に示します。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Dim Rireki As New PersonalHistory

Rireki.Histories.Add(
"1983年月犬上市立第2犬上小学校入学")
Rireki.Histories.Add(
"1989年月犬上市立第2犬上小学校卒業")
Rireki.Histories.Add(
"1989年月犬上市立二日中学校入学")
Rireki.Histories.Add(
"1990年月英検3級取得")

'TextBox1はMultiLine=Trueにして大きめに配置しくおくと良い。
TextBox1.Text = Rireki.HistoryMemo

■リスト9:フォーム側のプログラム。

HistoriesプロパティがArrayList型なので、このクラスの使用者はHistoriesプロパティからさらにArrayListクラスのメンバを呼び出すことができます。上記の例ではAddメソッドを呼び出してArrayListに値を追加しています。

また、Historiesプロパティは読み取り専用であるにもかかわらずArrayListAddメソッドを呼び出して値を追加することができるのが妙に感じられるかもしれません。

プロパティプロシージャにReadOnlyを指定した場合の動作は、「その値を変更できない」と言うよりは「その値をセットできない」と考えたほうが実際に近いのです。

ReadOnlyをつけても上記の例のようにメソッドやプロパティを呼び出してそのプロパティの状態をどんどん変更することは可能です。しかし、プロパティの値そのものをセットしようとするとエラーになります。たとえば次のコードはエラーです。

Dim Ar As New ArrayList
Dim Rireki As New PersonalHistory

Ar.Add(
"1983年月犬上市立第2犬上小学校入学")
Ar.Add(
"1989年月犬上市立第2犬上小学校卒業")
Ar.Add(
"1989年月犬上市立二日中学校入学")
Ar.Add(
"1990年月英検3級取得")

Rireki.Histories = Ar
'←ここでビルドエラーが発生します。

'TextBox1はMultiLine=Trueにして大きめに配置しくおくと良い。
TextBox1.Text = Rireki.HistoryMemo

■リスト10:フォーム側のプログラム。ビルドエラーになる例。

さきほどの例はプロパティの値そのものをセットしているわけではなくプロパティのメンバを呼び出していただけなのに対し、この例ではプロパティの値そのものをセットしようとしているのでReadOnlyに違反してビルドエラーとなるのです。

このような動作ですからプロパティの型にクラスを指定する場合はReadOnlyをつけることが少なくありません。

メモ  -  でも、構造体はだめです。

プロパティの型には構造体も指定できますが、利用する方法は少し異なります。

たとえば、フォームの位置を表すLocationプロパティはPoint構造体です。そしてこのプロパティに対してクラス感覚で次のようにプログラムすると「Expression は値であるため、代入式のターゲットにすることはできません。」と表示されてビルドエラーになります。


Me
.Location.X = 100
 

■リスト11:ビルドエラーになる。

これはクラスは参照型で構造体が値型であることに起因する違いです。このような書き方をした場合Location.XプロパティはLocationプロパティの暗黙的に作成されているコピーのXプロパティを指しているので値を代入しても意味がなく、親切なことにビルドエラーになります。(もしビルドエラーにならなかったらこのことに気がつかないでプログラムが完成したと思い込んでしまうプログラマがたくさん出現することでしょう。)

上記のようなプログラムを行いたい場合は次のようにします。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Dim Loc As Point

Loc =
Me.Location
Loc.X = 100
Me.Location = Loc

■リスト12:正常に動作する

 

 

6.引数付きプロパティ

 

さて、このクラスですが履歴を追加するときにRireki.Histories.Addと書くのはどうも違和感がありませんか?やはりRireki.Addとシンプルに書きたいですよね。

この場合はPersonalHistoryクラスでAddメソッドを定義して、コレクションは内部で持つことになります。

VB.NET2002対応 VB.NET2003対応 VB2005対応

'■PersonalHistory
'''
<summary>履歴を編集・管理します。</summary>
Public Class PersonalHistory

    Private _Histories As New ArrayList

   
'■Add
   
''' <summary>履歴を追加します。</summary>
   
''' <param name="Item">履歴</param>
   
Public Sub Add(ByVal Item As String)
        _Histories.Add(Item)
    End
Sub
    '■HistoryMemo
   
''' <summary>全履歴を取得します。</summary>
   
Public ReadOnly Property HistoryMemo() As String
       
Get

            Dim
Item As
String
           
Dim Result As String = ""

           
For Each Item In _Histories
                Result &= Item & vbNewLine
           
Next

            Return
Result

        End
Get
   
End Property

End
Class

■リスト13:クラス側のプログラム。

でも、こうやると履歴の追加はできるのに個々の履歴にアクセスできなくなってしまいます。そこで、個々の履歴にアクセスするためのItemプロパティも追加してみましょう。

VB.NET2002対応 VB.NET2003対応 VB2005対応

'■Item
''' <summary>Addメソッドで追加した個々の履歴を取得または設定します。</summary>
''' <param name="Index">履歴の番号。履歴を追加した順に0から始まる番号です。</param>
''' <value>新しい履歴の内容</value>
Public Property Item(ByVal Index As Integer) As String
    Get
        Return
_Histories(Index)
    End
Get
   
Set(ByVal value As String)
        _Histories(Index) = value
    End
Set
End Property

■リスト14:クラス側のプログラム。

このItemプロパティは今までにいくつか紹介したプロパティプロシージャと違ってIndexという引数がついていることに注意してください。履歴は複数登録できるので履歴を識別するための番号が必要なのです。そうでないと要求された履歴がいつ追加したどの履歴なのかわかりようがありません。

この番号はAddメソッドで変数_Historiesに文字列を追加したときにArrayListクラスの機能で自動的につけられる番号なので今回は自分で管理する必要はありません。受け取った番号をそのまま変数_Historiesに渡すだけです。

このようにプロパティにもメソッド同様に引数をつけることができます。もちろん必要とあれば2つ以上の引数を追加することもできます。

ここまで書けばクラスの使用者は次のように自由自在に履歴を操るプログラムを書くことができます。

VB.NET2002対応 VB.NET2003対応 VB2005対応

Dim Rireki As New PersonalHistory

Rireki.Add(
"1983年月犬上市立第2犬上小学校入学")
Rireki.Add(
"1989年月犬上市立第2犬上小学校卒業")
Rireki.Add(
"1989年月犬上市立二日中学校入学")
Rireki.Add(
"1990年月英検3級取得")

'2番目に追加した履歴の表示
MsgBox("2番目に追加した履歴は→" & Rireki.Item(1))

'3番目に追加した履歴の修正:「犬上市立」を「私立」に訂正
Rireki.Item(2) = "1989年月私立二日中学校入学"

'TextBox1はMultiLine=Trueにして大きめに配置しくおくと良い。
TextBox1.Text = Rireki.HistoryMemo

■リスト15:フォーム側のプログラム。個々の履歴には自在にアクセスできる。

実のところ履歴を削除する機能がないのですが、それは自分でいろいろ試してみてください。

 

7.既定のプロパティ

 

ところで、上記のプログラムでRireki.Item(2) =と書いている部分にみなさんは違和感を感じませんか?

機能としてはこれでよいのですが、VBにはじめから用意されているいろいろなクラスではこのような場面ではRireki(2) = のような書き方ができるようになっています。

この.Itemを省略できるようにしたいというわけです。

省略可能なプロパティは「既定のプロパティ」と呼ばれ、1つのクラスに1つだけ指定することができます。

指定するのはとても簡単で、プロパティの宣言にDefaultキーワード(読み方:Default = デフォルト)を追加するだけです。

VB.NET2002対応 VB.NET2003対応 VB2005対応

'■Item
''' <summary>Addメソッドで追加した個々の履歴を取得または設定します。</summary>
''' <param name="Index">履歴の番号。履歴を追加した順に0から始まる番号です。</param>
''' <value>新しい履歴の内容</value>
Default Public Property Item(ByVal Index As Integer) As String
   
Get
        Return
_Histories(Index)
    End
Get
   
Set(ByVal value As String)
        _Histories(Index) = value
    End
Set
End Property

■リスト16:クラス側のプログラム。Itemプロパティを既定のプロパティに設定。

なお、既定のプロパティにできるのは引数付きのプロパティだけです。

博士のワンポイントレッスン
V太 V太:最近講座の内容が難しくなってきたよ…。
B子 B子:ついて来られなくなっちゃったの?
V太 まだ何とか…。でも、なんで既定のプロパティにできるのが引数付きのプロパティだけなのかさっぱりわかりません。マイクロソフトが意地悪しているんですか?普通のプロパティも既定のプロパティにできだら便利なのに…。
博士 博士: ふぉふぉふぉ。いやいや。簡単なことじゃよ。たとえばじゃ。既定のプロパティを使ってプログラムするときにもし、引数がなかったら次のようになってしまうじゃろ?

ClassName = "こんにちは。"

V太 あれれ。なんか単なる変数への値の代入と同じですね。
博士 そうなのじゃ。変数自体への値のセットと、変数の既定のプロパティへの値のセットが同じ表現になってしまうのじゃ。ところが、既定のプロパティに引数があれば次のように書くことになるので区別できる。

ClassName(0) = "こんにちは。"

V太 なるほど〜!引数がないと構文上区別できないんですね!わかりました!

 

これで、そこそこに使いやすい履歴クラスができました。需要がないので実際に使われることはないでしょうがプロパティの勉強用にはちょうど良かったと思います。

最後に念のためにこのクラスとそれを利用するフォームの全体のプログラムを掲載しておきます。

クラス側

VB.NET2002対応 VB.NET2003対応 VB2005対応

'■PersonalHistory
'''
<summary>履歴を編集・管理します。</summary>
Public Class PersonalHistory

    Private _Histories As New ArrayList

   
'■Item
   
''' <summary>Addメソッドで追加した個々の履歴を取得または設定します。</summary>
   
''' <param name="Index">履歴の番号。履歴を追加した順に0から始まる番号です。</param>
   
''' <value>新しい履歴の内容</value>
   
Default Public Property Item(ByVal Index As Integer) As String
        Get
            Return
_Histories(Index)
        End
Get
       
Set(ByVal value As String)
            _Histories(Index) = value
        End
Set
   
End Property
    '■Add
   
''' <summary>履歴を追加します。</summary>
   
''' <param name="Item">履歴</param>
   
Public Sub Add(ByVal Item As String)
        _Histories.Add(Item)
    End
Sub
    '■HistoryMemo
   
''' <summary>全履歴を取得します。</summary>
   
Public ReadOnly Property HistoryMemo() As String
       
Get

           
Dim Item As String
           
Dim Result As String = ""

           
For Each Item In _Histories
                Result &= Item & vbNewLine
           
Next

            Return
Result

        End
Get
   
End Property

End
Class

■リスト17:クラス側のプログラム

 

フォーム側

VB.NET2002対応 VB.NET2003対応 VB2005対応

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim
Rireki As New PersonalHistory

    Rireki.Add(
"1983年月犬上市立第2犬上小学校入学")
    Rireki.Add(
"1989年月犬上市立第2犬上小学校卒業")
    Rireki.Add(
"1989年月犬上市立二日中学校入学")
    Rireki.Add(
"1990年月英検3級取得")

    '2番目に追加した履歴の表示
   
MsgBox("2番目に追加した履歴は→" & Rireki.Item(1))

   
'3番目に追加した履歴の修正:「犬上市立」を「私立」に訂正
   
Rireki(2) = "1989年月私立二日中学校入学"

   
'TextBox1はMultiLine=Trueにして大きめに配置しくおくと良い。
   
TextBox1.Text = Rireki.HistoryMemo

End
Sub

■リスト18:フォーム側のプログラム

 

発展学習  -  コレクションを自作クラスで表現する方法

今回は内部でArrayList型の変数を持ってコレクションのように扱えるクラスを作成しましたが、実際のコレクションならば当然もっているいくつかの機能が欠けています。

たとえば、For Eachで値を列挙できるのがコレクションの特徴ですが今回のクラスではそれができませんし、その他にもコレクションを要求されている場所で今回のクラスを指定することができないなどかなりの不便があります。

実際に自作のコレクションを作る場合には、既存のコレクションを継承して作ると楽です。継承を使用した場合は普通のコレクションが持っている機能は何もプログラムしなくてもすべて利用できます。

継承して作成した場合の一例を紹介します。

VB.NET2002対応 VB.NET2003対応 VB2005対応

'■PersonalHistory
'''
<summary>履歴を編集・管理します。</summary>
Public Class PersonalHistory

    Inherits ArrayList

    '■HistoryMemo
   
''' <summary>全履歴を取得します。</summary>
   
Public ReadOnly Property HistoryMemo() As String
       
Get

           
Dim Result As String = ""
           
Dim en As IEnumerator = Me.GetEnumerator

            Do While en.MoveNext
                Result &=
CStr(en.Current) & vbNewLine
           
Loop

            Return
Result

        End
Get
   
End Property

End
Class

■リスト19:クラス側のプログラム。継承を利用した例。

これだけのコードで本文中で紹介したクラスの機能 + 通常のコレクションとしての機能があります。継承については中級講座で扱う予定です。