クラスモジュールを用いた自作クラスのプロパティについて
クラスモジュールの使い方を練習するため、遊び半分にプログラムしてみた。
高橋麻奈さんの『やさしいJava』に倣って、車オブジェクトを作るという体で。
とりあえず、Sheet1に、上の画像のような表を作る。
A、B列の1行目にはコマンドボタンを設置している。
まずは、「車クラス」の設計。
クラスモジュールを挿入し、「オブジェクト名」を「Car」にする。
クラスモジュールにコードを記述。
Option Explicit
'Field Variables
Private Number_ As Integer
Private Name_ As String
Private Gas_ As Double
Private Speed_ As Integer
'Accessor
Public Property Let Number(ByVal New_Number As Integer)
If CStr(New_Number) <> "" Then
Number_ = New_Number
End If
End Property
Public Property Get Number() As Integer
Number = Number_
End Property
Public Property Let Name(ByVal New_Name As String)
If New_Name <> "" Then
Name_ = New_Name
End If
End Property
Public Property Get Name() As String
Name = Name_
End Property
Public Property Let Gas(ByVal New_Gas As Double)
If New_Gas < 0 Then
MsgBox "ガソリン量がマイナスて……。"
MsgBox "ふざけるなボケーーー!", vbCritical
MsgBox " _________" & vbCrLf & _
" / \ " & vbCrLf & _
"/ /・\ /・\ \" & vbCrLf & _
"|  ̄ ̄  ̄ | ち~んw" & vbCrLf & _
"| (_人_) |" & vbCrLf & _
"| \ | |" & vbCrLf & _
"\ \_| /"
End
ElseIf New_Gas > 100 Then
MsgBox "そんなにガソリンが入るかい、ボケ!", vbCritical
MsgBox " _________" & vbCrLf & _
" / \ " & vbCrLf & _
"/ /・\ /・\ \" & vbCrLf & _
"|  ̄ ̄  ̄ | ち~んw" & vbCrLf & _
"| (_人_) |" & vbCrLf & _
"| \ | |" & vbCrLf & _
"\ \_| /"
End
Else
If CStr(New_Gas) <> "" Then
Gas_ = New_Gas
End If
End If
End Property
Public Property Get Gas() As Double
Gas = Gas_
End Property
Public Property Let Speed(ByVal New_Speed As Integer)
If New_Speed < 0 Then
MsgBox "スピードがマイナスて……。"
MsgBox "ふざけるなボケーーー!", vbCritical
MsgBox " _________" & vbCrLf & _
" / \ " & vbCrLf & _
"/ /・\ /・\ \" & vbCrLf & _
"|  ̄ ̄  ̄ | ち~んw" & vbCrLf & _
"| (_人_) |" & vbCrLf & _
"| \ | |" & vbCrLf & _
"\ \_| /"
End
ElseIf New_Speed > 400 Then
MsgBox "そんなスピード出るか、ボケ!", vbCritical
MsgBox " _________" & vbCrLf & _
" / \ " & vbCrLf & _
"/ /・\ /・\ \" & vbCrLf & _
"|  ̄ ̄  ̄ | ち~んw" & vbCrLf & _
"| (_人_) |" & vbCrLf & _
"| \ | |" & vbCrLf & _
"\ \_| /"
End
Else
If CStr(New_Speed) <> "" Then
Speed_ = New_Speed
End If
End If
End Property
Public Property Get Speed() As Integer
Speed = Speed_
End Property
'Constructer
Private Sub Class_Initialize()
Number_ = 0
Name_ = "名無し"
Gas_ = 0#
Speed_ = 4
End Sub
'Methods
Public Sub showCar()
MsgBox "車・" & Name & "の" & vbCrLf & _
"ナンバーは、" & Number & "、" & vbCrLf & _
"ガソリンは、" & Gas & "リッターです。" & vbCrLf & _
"本気を出せば、" & Speed & " km/hで走ります。"
End Sub
Public Sub runCar()
If Me.Gas <> 0 Then
MsgBox Name & "行きま~す!" & vbCrLf & _
Me.Speed & " km/hでぶっ飛ばすぜ!" & vbCrLf & _
"ぶおおおおおん!"
If Me.Gas > Me.Speed * 0.1 Then
Me.Gas = Me.Gas - Me.Speed * 0.1
Else
Me.Gas = 0
MsgBox "ぷすん!……" & vbCrLf & _
"ガソリンがなくなったようだ……。"
End If
MsgBox Me.Name & "のガソリン量が、" & Me.Gas & _
"リッターになりました。"
Else
MsgBox Name & "行きま~す!" & vbCrLf & _
Me.Speed & " km/hでぶっ飛ばすぜ!" & vbCrLf & _
"ぷすん!……" & vbCrLf & _
"ガソリンがないようだ……。"
End If
End Sub
「Car」というオブジェクトに「Number」「Name」「Gas」「Speed」というプロパティを設置したわけだ。
「Number」を例に取ると、次のようなコードで実装していることになる。
Private Number_ As Integer 'クラス内での値保持用変数
Public Property Let Number(ByVal New_Number As Integer) '値設定用プロシージャ
Number_ = New_Number
End Property
Public Property Get Number() As Integer '値取得用プロシージャ
Number = Number_
End Property
Carクラスを使うには、変数を宣言して、New演算子でインスタンス化すれば良い。
以後、その変数をオブジェクトとして使用できる。
たとえば、プロシージャ内で、
Dim car1 As Car 'Carクラス型の変数car1を宣言
と宣言し、
Set car1 = New Car
とすれば、以後「car1」をオブジェクトとして扱えるということ。
で、本題。
オブジェクトcar1のNumberプロパティに値を設定するときは、当然、たとえば
car1.Name = 1234
などとすれば良い。
で、大切なのは、このときにどんな処理が為されているか、という流れを理解しておくこと。
順を追って書いておこう。
【プロパティへの値の設定】
- car1.Name = 1234 が実行される→Property Let Name プロシージャに1234が渡される
- Property Let Nameプロシージャの仮引数New_Nameが1234を受け取る Private変数Name_に1234が代入される
【プロパティからの値の取得】
※たとえば、car1オブジェクトのNameプロパティをメッセージボックスに表示するとしよう。
- Msgbox car1.Name が実行される。
- car1のNameプロパティを取得するためにProperty Get Nameプロシージャに処理が移る
- Nameプロパティの値はPrivate変数Name_に入っているので、NameプロパティにName_の値(1234)を代入する
- car1.Nameの値として「1234」を得て、メッセージボックスには「1234」が表示される。
という流れで値を設定したり、取得したりしている。
値の設定と取得の際に、一旦Private変数を噛ますというのは一見無駄なようだが、使いようによってはいろいろ便利だったりする。
追記
2018年2月25日時点での考えを追記します。
- 「プロパティ」に値が入っているのではなくて、あくまでも値を持っているのはPrivate変数。
- 従って、変数が持っている値は、他のモジュールからは設定することも取得することもできない。
- 要するに、設定する場合はProperty Let、取得する場合はProperty Getを介する他ない。
- プロパティに値を代入しようとしたとき、すなわち、たとえば、
car1.Name = "hoge"
が評価されるときに引数「hoge」を渡してProperty Letが実行され、Private変数Name_に「hoge」が代入される、ということ。 - 逆に、プロパティが参照されたとき、すなわち、たとえば、
str = car1.Name
が評価されるときには、Property Getが実行され、Private変数Name_にぶち込まれている値が返って、変数strにぶち込まれる、ということ。
このしくみによって、仮にプロパティの値を設定/取得する手続きが相当複雑だったとしても、コーディング時には、変数に値をぶち込んだり、変数から値を取り出すかのようにカンタンにプロパティを使うことができる、ということ。
このあたり、実際に使ってみないといまいちピンと来にくいと思うが、たとえば、
このように、レジストリの値を設定/取得するようなめんどくさそうなことでも、ひとたびPropertyにしてしまえばアホみたいにカンタンに実行できることになる。
複数のモジュールをまたがるような処理があるとき、Public変数を使う代わりにPropertyの使用を検討してみてはいかがだろうか。