書籍転載
|
本コーナーは、日経BPソフトプレス発行の書籍『文法からはじめるプログラミング言語Microsoft Visual Basic入門』の中から、特にInsider.NET読者に有用だと考えられる章や個所をInsider.NET編集部が選び、同社の許可を得て転載したものです。基本的に元の文章をそのまま転載していますが、レイアウト上の理由などで文章の記述を変更している部分(例:「上の図」など)や、図の位置などを本サイトのデザインに合わせている部分が若干ありますので、ご了承ください。『文法からはじめるプログラミング言語Microsoft Visual Basic入門』の詳細は「目次情報ページ」もしくは日経BPソフトプレスのサイトをご覧ください。 |
ご注意:本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。 |
■11.5 拡張メソッド(Visual Basic 2008)
Visual Basic 2008から導入された拡張メソッドは、既にあるクラスに、継承せずにメソッドを追加するものです。派生クラスとして機能を追加するのではなく、あたかも最初からそのメソッドが存在していたかのように、元のクラスのメソッドとして呼び出すことができるのです。
この機能が強力なのは、ユーザー定義のクラスだけでなく、.NET Frameworkであらかじめ定義されているクラスに対しても機能が追加できるという点です。さらに、継承できないクラス(NotOverridableが指定されたクラス)にもメソッドを定義できます。ただ、拡張メソッドはクラスの外部から機能を拡張するものなので、元のクラスのPrivateメンバにはアクセスできません。
図11-7 拡張メソッド |
拡張メソッドの定義には、System.Runtime.CompilerServices名前空間の拡張属性<Extension()>でマークする必要があります*。この属性の指定によって、Visual Basicのコンパイラは、拡張メソッドであることを判断します。また追加するメソッドの最初のパラメータには、拡張するクラスを指定します。
*) 属性は、データ型やメソッド、プロパティなどの要素に注釈を付ける機能です。属性が付いていても、要素自身の機能には何の影響もありません。Visual Basic コンパイラや他のアプリケーションが、属性の情報を参照することで、その要素の使用方法を判断します。ここでの属性も、拡張メソッドであることを、コンパイラに指示するためのもので、それ以上の意味はありません。 |
|
|
[構文]拡張メソッドの定義 |
●11.5.1 ユーザー定義のクラスを拡張する
まず、ユーザー定義のクラスを拡張してみます。次のサンプルコードでは、TestClassを拡張するために、ExtendTestという名前のモジュールで拡張メソッドcheckJを定義しています(モジュールについてはコラム「モジュールとは」を参照してください)。このように、拡張メソッドはモジュールで定義する必要があります。
|
|
[サンプル]extend1.vb |
TestClassクラスでは、体重と身長を保持するプロパティを定義しています。身長の場合、初期値をセンチメートル単位と見なして、100で割ったメートル単位の値を取得できるようにしています。BMIメソッドは、肥満度を示すBMI値を返します。
拡張メソッドcheckJでは、BMI値を利用して肥満度の判定を行い、結果を表示します。あたかもTestClassのメソッドであるかのように、a.checkJ()という形で呼び出しています。
●11.5.2 .NET Frameworkのクラスを拡張する
今度は、.NET Frameworkで定義されているStringクラスを拡張してみましょう。次のサンプルコードでは、拡張メソッドとして16進数の文字列を数値に変換する処理を定義しています。なお、元のクラスに同じ名前のメソッドがあった場合はエラーにはならず、単に拡張メソッドが無視されます。
|
|
[サンプル]extend2.vb |
●11.5.3 拡張メソッドと名前空間
先ほどのサンプルコードでは名前空間を定義していないため、拡張メソッドも拡張されるクラスも、ルート名前空間にあることになります。
拡張されるクラスと異なる名前空間で拡張メソッドを定義している場合は、次のようにImportsステートメントで、使用したい拡張メソッドが含まれる名前空間の使用を宣言します。拡張メソッドは通常のメソッドのように完全修飾名で指定できないため、どの名前空間の拡張メソッドを使用するかを指定するためには、必ずImportsステートメントが必要です。
先ほどの「extend2.vb」を書き換えて、拡張メソッドを別の名前空間に定義した場合のサンプルコードを示します。なお、この例ではルート名前空間を「ConsoleApplication」としています。
|
|
[サンプル]extend3.vb |
拡張メソッドは名前空間Xで定義されているため、「Imports ConsoleApplication.X」の宣言を削除すると、拡張メソッドが見つからずエラーになります。
当然ながら、同じ名前空間に同じ名前の拡張メソッドを定義すると、どの拡張メソッドを呼び出すのか特定できないためエラーになります。また、同じ名前の拡張メソッドを含む複数の名前空間の使用を宣言すると、同じ理由によりエラーになります。
【コラム】モジュールとは |
一般的な意味でのモジュールとは、ハードウェアやソフトウェアの、ひとまとまりの機能や要素のことを指します。Visual BasicでのModule(モジュール)とは、クラスのように、定義されたコードをまとめたものです。.NETに対応する前のVisual Basicでは、モジュール単位でプログラムを作っていくことが、標準的な作成方法でした。 しかし、Visual Basic .NET以降では、完全にオブジェクト指向に対応したこともあり、クラスと似て非なるModule(標準モジュール)機能は、(拡張メソッドなど一部の機能を除いて)過去との互換性のためにある機能と言えます。 標準モジュールがクラスと異なるのは、インスタンス化できないことです。標準モジュールのデータは、1つしか存在しません。標準モジュールで定義された変数やメソッドは、すべて共有(Shared)となり、そのモジュール自身以外のどこにも属さない独立したものになります。つまり、どこでも使えるデータとコードとなるため、オブジェクト指向にはなじまない機能であり、むやみに標準モジュールを使用するのは避けた方がよいでしょう。 |
■
書籍『文法からはじめるプログラミング言語Microsoft Visual Basic入門』の部分転載は今回が最終回です。@ITで公開した部分は「目次情報ページ」の各リンクから参照できます。
「文法からはじめるプログラミング言語Microsoft Visual Basic入門」 |
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|