Visual Basic |
言語機能を中心に、歴代Visual Basicの新機能をまとめます。今回はVB2〜VB6までを扱います。
概要
|
昔のVisual Basic マガジン 第1号(1995年)の記事を読んでふいに昔のVisual Basicに触ってみたくなりました。しかし、環境がありません。VirtualPCにWindows98をインストールするところからはじめました。すっかり忘れていたのですが当時のCDはCDブート機能もなく、なかなか苦労しました。
Windows98のインストールができたら、私が手に入る最も古いVBである、VB2をインストールしてみました。
インストールしようとするとなんと 6MB もの空き容量が必要であるという警告が表示され時代を感じました。
私はVBは4.0から使っていたので、VB2を実際に触るのは初めてです。起動してみて驚きました。まるでおもちゃのように見えます。でも、ためしに簡単なプログラムを作成してみるということはすぐにできました。もちろんはじめてさわったVBがVB.NET以降である人はこうはすんなりできないかもしれません。
■画像1:Visual Basic 2.0 IDE。当時はIDEは複数のウィンドウからできており、背景のデスクトップが隙間から見えていました。
一番感心したのは、「おもしろそうだ」、「やってみたい」というわくわくする雰囲気があったことです。この感覚は忘れていないつもりだったのですが、実際には忘れていたことがわかりました。
その雰囲気を感じたのはVB2に付属している簡単な紹介デモというかスライドショーです。VBの魅力をわかりやすく伝えてくれます。
■画像2:VB2に付属しているVisual Basicの紹介デモ。
強調されているメッセージは「最も簡単な Windows アプリケーション作成ツール」です。思い起こせば、かつてVB5を買ったとき、私はラーニングエディションという一番機能の少ない入門者向けのものを買ったのですが、学習用の教材CDが付属していて、そのCDの内容を少しずつ進めるのが当時とても楽しかったものです。今でも楽しい記念にそのCDはとっておいてあります。
さて、現時点の最新版Visual Studio 2013はどうでしょうか?VB2から20年近い歳月が過ぎています。機能はすごく強力になりました。VBだけでほとんどのアプリケーションを作成することができます。でもその分複雑になり、不親切になっています。一番の原因は敷居の高さだと思います。VB2の敷居の低さを見て実感しました。
マイクロソフトは啓蒙活動にも力を入れていていろいろな教材や資料を提供してくれています。でもうまくいえませんがどうも当時のものとは雰囲気が違います。変わったのは私のほうかもしれませんが。
VB2013では機能や生産性はとても重視されていますが、敷居の低さではVB2のほうに軍配が上がると思います。高度化した代償なのかもしれません。いつの間にかわくわく感も忘れていました。
話が長くなってしまいました。このようなことを考えているうちに、歴代VBの進化の歴史が気になりまとめてみようと思い立ちました。IDEや各種アーキテクチャを含めると大変だし、現在では使われていないものの話がたくさん出てくるので言語仕様に着目してみました。
今、私の手元には私が作成したVB2からVB2013までの主な新機能の一覧があります。今回はこのうちVB6までを記事にします。ここに書いていない細かい機能もあるのですが、私の判断で割愛しています。
新機能を調べるためにいくつかの古い資料やVB2のヘルプ、VB4のヘルプ、VB6のヘルプを参考にしましたが、いまいちよくわからなかったり、ドキュメントに書いてあるだけで実際に試したり、確認していないものもあるので、間違った情報があるかもしれません。今のうちに謝ります。ごめんなさい。
Variant型を使うと文字・数字・Nullなどあらゆる値を代入できます。
■画像3:VB2でのVariant型使用例
VB.NET(2002)以降はVariant型は廃止され、Object型に引き継がれました、予約語としては残されており、VB2013でもVariantという名前を変数やクラスの名前に使用することはできません。またVisual Studio 2013で As Variant と記述して改行すると自動的にAs Object に変更されます。
■画像4:VB2013でもVariantという名前を定義しようとするとエラーになる。
1回作成したフォームのインスタンスを複数作成することができます。もはやたくさんのフォームを表示するためにたくさんのフォームをプログラムする必要はありません。
Dim fa As New Form2 fa.Show Dim fb As New Form2 fb.Show |
オブジェクト指向の発想ではおかしな話なのですが、おそらくVB1〜VB6の間、フォームは特別な存在でインスタンス化せずに Form2.Show のように呼び出すことができました。当時はフォームがほとんど常にプログラムの中心にあったことと、VB自体があまりオブジェクト指向的でなかったことから特に問題なくこの書き方が浸透していました。
VB2ではオブジェクト指向的に New を使ってフォームのインスタンスを作成することはできるようになりましたが、この時点ではフォームのメンバーをPublicにすることはできなかったり、そもそもコンストラクタも存在していなかったので扱いは不便だったことが想像されます。
VB.NET(2002)以降は、オブジェクト指向が本格的に導入されたため Form2.Show のような書き方はできなくなりましたが、それまで Form2.Show という書き方に慣れていたたくさんのVBプログラマにとっては扱いづらく感じられました。この批判を受け、VB2005からは Form2.Show という書き方が復活しました。内部の仕組みはVB2のときとはまったく異なっており、「フォームの既定のインスタンス」と呼ばれています。VB2013でも利用可能です。
つまり、結局のところ、Form2.Showという書き方ができないのはVB.NET(2002)とVB2003だけです。
Form2.Show と書けるか? |
Dim f As New Form2 f.Show と書けるか? |
||
---|---|---|---|
VB1 | ○ | × | フォームは特別な存在だ という時代 |
VB2 | ○ | ○ | |
VB3 | ○ | ○ | |
VB4 | ○ | ○ | |
VB5 | ○ | ○ | |
VB6 | ○ | ○ | |
VB.NET(2002) | × | ○ | オブジェクト指向に従うべきだ という時代 |
VB.NET 2003 | × | ○ | |
VB2005 | ○ | ○ | 旧VBプログラマもいることだし少しは妥協してもいいだろう という時代(時代というほどでもないですが) |
VB2008 | ○ | ○ | |
VB2010 | ○ | ○ | |
VB2012 | ○ | ○ | |
VB2013 | ○ | ○ |
なお、現在ではオブジェクト指向が浸透しているので、Form2.Show という書き方が可能であるとしても使用すべきでないという考え方のほうが一般的であると思います。
Visual Basic 3.0ではデータベースアクセスが大幅に強化されたようですが、言語としての新機能はないようです。
Publicキーワードを使うとフォームやクラスで定義したメンバーを外部から呼び出せるようになります。
外部から呼び出されたくないメンバーにはPrivateをつけます。
Public Sub Test() MsgBox "Hello!" End Sub |
少なくともVB2の時点ではフォームに記載したメンバーはすべてPrivateの効果、コードモジュール(UIを持たないプログラムの集合)に記載したものは明示的にPrivateをつけない場合はすべてPublicの効果となっていたようです。Privateというキーワードは少なくともVB2の時点では存在していました。
クラスはUIを持たないコードのみのモジュールで、自由にインスタンスを作成して使用します。
VB4時点でのクラスには、継承機能がなく、インターフェースの実装ができず、イベントを持つことができませんが、それ以外はVB2013のクラスと同じような感覚で使用できます。ポリモーフィズムは遅延バインディングによって実現されます。これは現代風(2014年時点)で言うところのダックタイピングに近い発想です。VB5ではImplementsキーワードが導入され、クラスがインターフェースを実装できるようになります。VB.NET(2002)が発売されるまで、VBがオブジェクト指向言語であるかどうか議論を呼びました。
フォームやクラスにはプロパティを追加できます。
コレクションは配列に似ていて、要素の追加や削除が簡単にできます。配列のように事前に上限を決めておく必要はありません。
コレクションの要素を順に処理するための新しいループの構文 For Each が追加されました。
1つのオブジェクトに対しメソッドやプロパティを次々と呼び出すのに便利なWith 〜 End With構文が追加されました。With 〜 End Withの内部では、オブジェクト名を省略して記述することができます。
With Label1 .Height = 100 .Width = 200 .Caption = "Hello!" End Sub |
LabelのプロパティがVB.NET(2002)で大きく変更されたため、この例はVB4,56以前でしか実行できませんが、With自体はVB2013でも同じ構文で使用できます。
コンパイラに対して指示を行える特別な構文が追加されました。これらの構文は通常のプログラムと区別するために先頭に # がつきます。#If を使うとコンパイルする条件を指定することができます。
VB4発売当時は16ビットから32ビットへの移行の過渡期だったため、16ビット用のコンパイルと32ビット用のコンパイルを簡単に切り替える目的で導入されたようです。
#If Win16 Then 'ここに16ビット用のコードを書く #ElseIf Win32 Then 'ここに32ビット用のコードを書く #End If |
条件付コンパイルはVB2013でも使用できますが、あまり出番はなく、デバッグ用のコードとリリース用のコードを切り替える目的で使用する場合がごくたまにあります。
はっきりした情報は見つけられませんでしたがこのころ日付型が追加されたはずです。VB1時点では日付と時刻を表現する特別な方法はおそらくなく、VB2の時点ではVariant型で内部情報日付という値の持ち方をしていたようです。
なお、期間をあらわす型が追加されたのはVB.NET(2002)で.NET FrameworkのTimeSpan型が導入されたのが最初です。
この強力な新しい演算子 AddressOf が導入されたことで VB でできることが一挙に増えました。
AddressOf演算子は、たったひとつの演算子に過ぎないのだが、Visual Basicを使いこなす上で、実に強力な味方となる。Visual Basicの制限を大きく拡張してくれる。
Visual Basic Magazine 1997年6月号 「Visual Basic 5.0の新しい言語仕様:API編」 酒井法雄著 から引用。この記事はAddressOfの説明がすべて。
AddressOfはVBからWindowsAPI(Win32APIとも言います)を呼び出す場合に使用することが想定されていました。もともとVBにはおそらく初代VB1のころからWindowsAPIを呼び出す機能があって、VBが持っていない音楽再生機能などでもWindowsが公開している機能を呼び出して使用することができました。
ところが、WindowsAPIはC++で作られていたため、引数に関数のアドレスが必要になるものが多数ありました。VBではアドレスという発想はないので、このようなWindowsAPIは呼び出せなかったのですが、VB5で登場したAddressOf演算子で、ついに関数のアドレスが取得できるようになり多数の魅力的なWindowsAPIを新たに呼び出すことができるようになりました。これを使って実現されるサブクラス化という技法が当時の私には輝いて見えました。
ところで、AddressOfで関数のアドレスは取得できるようになったのですが、依然としてVBには「そのアドレスにある関数を実行する」という機能は実装されていませんでした。この機能が実装されれば、現在で言うところのデリゲートが実現でき、非常に有用だと思ったのですが、今振り返ると、当時もしこの機能が実装されていたら、非常にどこから関数が呼び出されているか非常にわかりにくいプログラムが多数出現していたかもしれません。
それでも、あきらめきれない一部の人たちはコールバック機能があるWindowsAPIを利用してAddressOfで取得したアドレスにある関数を実行させる方法を編み出しました。
なお、VB.NET(2012)でデリゲートが導入されたので、このような自助努力は不要になりましたが、デリゲートを利用する際にはやはりAddressOfが必要です。
知らない人から見るとなぜデリゲートやイベントハンドラを指定するときにメソッド名を直接記述するのではなくAddressOf演算子を経由しなければいけないのか疑問に思うかもしれませんね。
イベントを自作できるようになりました。Event文でイベントを宣言し、発生させたい場所でRaiseEventを実行します。
これにより自作コントロールや自作のクラスから、呼び出し元に簡単にコールバックできるようになりました。
PrivateでもPublicでもない新しい適用範囲 Friend が導入されました。
Friendは同じプロジェクト内ならばアクセス可能、異なるプロジェクトからはアクセス不可能という適用範囲です。
なお、Protectedが導入されるのはVB.NET(2002)からです。これでVB2013現在の適用範囲がすべて出揃います。
適用範囲を示すキーワード | 初登場 |
---|---|
Private | おそらく VB1 |
Public | VB4 |
Friend | VB5 |
Protected | VB.NET(2002) |
列挙型は本質的には定数ですが、プログラムでコードを入力する際に意味のある定数をグループ化する役割があります。今で言うところの列挙体です。
クラスはインターフェースを実装できるようになりました。インターフェースを実装するにはImplementsキーワードを使用します。なお、VB5, 6の時点ではインターフェースを定義するにはタイプライブラリを使用するか、クラスを作成する必要がありました。
この使い方や意味が小難しかったため、このインターフェースの実装機能はかなり上級者向け機能と考えられ、ほとんど活用されなかったようです。
CallByNameを使うとメソッドを文字列で呼び出すことができます。この機能の導入で、実行時に動的に制御できる部分が増えました。
Private Sub Command1_Click() CallByName Me, "Test", VbMethod End Sub Public Sub Test() MsgBox "Test" End Sub |
VB.NET(2002)以降ではリフレクション機能が導入され、CallByNameと同じことができますが、手軽さでは今でもCallByNameが優れています。
Private Sub Button1_Click(sender As System.Object, e As
System.EventArgs) Handles Button1.Click CallByName(Me, "Test", CallType.Method) End Sub Public Sub Test() MsgBox("Test") End Sub |
ユーザー定義型とはVB2013で言うところの構造体です。
信じが難いことに、VB5までは関数の引数や戻り値にユーザー定義型は使用できませんでした。また、配列を戻り値にすることができませんでした。
そのため、どうしてもプロジェクト全体で有効なグローバル変数を介して値をやりとりすることが増え、全体として読みにくいプログラムになってしまうことがありました。
VB6ではそれがだいぶ緩和されました。
実行時にコントロールを動的にフォームに配置できるようになりました。ただ、従来からコントロール配列を方法を使ってほぼ同じようなことは実現できていたのであまりありがたみはなかったように思います。
WithEventsキーワードと併用することで、動的に追加したコントロールからイベントを受け取ることも可能です。
便利ないくつかの関数が追加されました。特にSplitとReplaceは需要も高く多く活用されたようです。これらの関数はRound以外はVB2013でも使用できます。
追加された関数