まえがき
もう殆どの方の目の前からはVB6は駆逐されたか幸いにも目にしたことがないかと思いますが私の職場ではVB6での新規開発は流石にありませんが機能追加・変更は時々あります。勿論VB6の面倒見るのをやめたいのは山々ですがなぜいまだにしぶとく生き残っているのか・生き残ってはならない理由など考えてみたいと思います。人1と金2の問題なのは良くわかっているのでプログラミング言語としてどうなの?という話です。
VB6は1998年にリリースされ今年で22年になります。VB6のMSのサポートは2008年に延長サポート期限が切れたので今使って何かあってもMSとしてはもう知らない状態の言語です。
生き残ってる理由(と言うか、これくらいは出来るでー)
ActiveX.DLL/ActiveX.EXEが作れる
ActiveX.DLL/ActiveX.EXEはさほど使い勝手の良いものではありませんがDLL化することで資産の再利用が可能となっています。作成したDLLはネイティブではないのでレジストリ登録が必要です。
> regsvr32 hoge.dll
API呼び出し
WindowsAPIを呼び出して利用することができます。これでVBだけでは実現できないことが殆どできてしまいます。
Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function SetForegroundWindow Lib "user32" _
(ByVal hWnd As Long) As Long
Private Sub foo(ByVal strClassName As String)
Dim lngHwnd As Long
lngHwnd = FindWindow(strClassName, vbNullString)
Call SetForegroundWindow(lngHwnd)
End Sub
DictionaryとCollection
Collectionは元々搭載されていますがDictionaryはMicrosoft Scripting Runtimeを参照設定することで利用できるようになります。Collectionはちょっと変わっていてキーと共にDictionary的な使い方もできますしAdd()する型は同じである必要はありません。ちなみにStackとかQueueとかはありませんしCollectionを配列に変換したかったらループさせて代入するしかないです3。
オブジェクト指向
オブジェクト指向の三大要素と言われる「継承」「カプセル化」「ポリモーフィズム」のうち「継承」は実装されていません。確かに継承が無いと殆ど一緒で一部だけ動きを変えたい複数のクラスに共通処理まで実装する必要があるのですがポリモーフィズムが無いよりはマシかなと思います。
「カプセル化」についてはスコープがPublicとPrivateしかありませんがまぁなんとか(汗) 併せてプロパティもありますのでなんとなくそれっぽくはなりますがちょっと貧弱です。Friendという修飾子もありますが、同一プロジェクトの中でのみアクセス可能となるのでC#で言うところのinternal相当でしょうか。
Private data As String
Public Property Get Hoge() As String
Hoge = data
End ProPerty
Public Property Let Hoge(ByVal strValue As String)
data = strValue
End Property
「ポリモーフィズム」についてはInterfaceが使えます。ただVB6管轄のオブジェクトにインターフェースというものはなく通常のクラスを用います。メソッドとプロパティのみインターフェースとして記述できます。
' インターフェースとして扱うクラス
Public HP As Integer '変数の宣言をしているように見えて実際はこの名称のget/setプロパティの宣言
Public Sub Skill()
End Sub
Monsterインターフェースを実装するAkineクラス
Implements Monster 'Monsterインターフェースを実装する宣言
Private mHP As Integer
' プロパティ・メソッド名にインターフェース名が必ず付く
Private Property Let Monster_HP(ByVal RHS As Integer)
mHP = RHS
End ProPerty
Private Property Get Monster_HP() As Integer
Monster_HP = mHP
End Property
Private Sub Monster_Skill()
Call MsgBox("蛇骨姫の龍鳴")
End Sub
同、Daiaクラス
Implements Monster
Private mHP As Integer
Private Property Let Monster_HP(ByVal RHS As Integer)
mHP = RHS
End ProPerty
Private Property Get Monster_HP() As Integer
Monster_HP = mHP
End Property
' Akineクラスと異なるのはこのメソッドのみ
Private Sub Monster_Skill()
Call MsgBox("神器宿装・アーウィル")
End Sub
呼び出し元。
'型指定のできないCollectionとして宣言してしまうと
'Monsterのサブクラスとして扱えなくなるので敢えてMonster型の配列で扱う
Private monsters() As Monster
Private Sub Form_Load()
ReDim monsters(2)
Dim m As Monster
Set m = New Akine
m.HP = 7497 'アクセスする時にはインターフェース名は不要
Set monsters(1) = m
Set m = New Daia
m.HP = 3810
Set monsters(2) = m
Dim i As Integer
For i = 1 To UBound(monsters())
Call MsgBox("HP=" & monsters(i)) '「HP=7497」「HP=3810」が表示される
Call monsters(i).Skill '「蛇骨姫の龍鳴」「神器宿装・アーウィル」が表示される
Next
End Sub
コメントにも書きましたがサブクラスは配列で扱う必要があるのでループするところでforeach的な処理はできません4。また、インターフェースにイベントの宣言は書けない(書いても無視)ので各サブクラスからのイベント通知ができません。各サブクラスにイベントを書くことはできますがインターフェースに定義が無い以上は意味がないので発火できないです(何か別の手段を考える必要があります)
あとがき(+生き残ってはならない理由・・・は言い過ぎ)
と、まぁこんな感じでプログラミング言語としては20年以上前の言語でそこから進化してないので昨今の「こんなめんどくさいこと書いてられるかよっ!」とか「こんな意図のわかりにくい実装書かすなよっ!」が何も解消されていませんが、そこそこ最低限は出来てしまうのでそれほど役立たずにならないのは生き残っている理由の一つと考えられます。が、言語仕様云々よりも操る人間の方の進化が止まってしまっている方が要因として大きいと思います。VB6やったらこう書くよねをC#のソースで見るにつけ悲しい気持ちになります・・・
もうあんまりVB6を書きたくない理由の一つは前記のサンプル見ればわかりますが兎に角書くコード量が多いことです。無いものを挙げればLINQ、型推論、ラムダ式、自動実装プロパティ、オブジェクト・コレクション初期化子など無いものばかりなので色々と一から書くものが多いです。これはもう車輪の再発明の領域に足を踏み入れてる感が。いや、LINQとかラムダ式の実装とかは無理ですが例えば
Option Explicit
Private queueData As Collection
Private Sub Class_Initialize()
Set queueData = New Collection
End Sub
Public Sub Enqueue(ByVal value As Variant)
Call queueData.Add(value)
End Sub
Public Function Dequeue() As Variant
If queueData.Count >= 1 Then
Dequeue = queueData.Item(1)
Call queueData.Remove(1)
Else
Dequeue = Null
End If
End Function
Public Property Get Count() As Integer
Count = queueData.Count
End Function
万事こんな調子で。
言語仕様も今となっては貧弱ですが冒頭に書いた人と金の方が問題かなとは思います。20代後半から30代前半の人がVB始めると20年強経つわけですから50才前後。もうこれくらいになると「今できることだけしたい!新しいことなんか覚える気はさらさらない!」という人もいます。Qiita覗きに来たり投稿したりする人はそんなことないでしょうがQiita?喰えるのか!?という人もいますから。また長い目で見れば乗り換えた方がクライアントも結局コスト抑えられるとは思うのですが目先の出費のことしか考えない人も多いわけで。
そんなこんなで負の遺産が末端エンジニアに降り注ぐのではよやめたいと願う今日この頃。