インデクサ
インデクサを使うとクラスを配列のように扱う事ができる。
Javaにはインデクサは存在しない。
インデクサの実装は簡単、以下にその例を示す。
上記のコードの5行目のIndexerSample1というクラスに、インデクサを実装している。
インデクサの実装により、クラスIndexerSample1は30,33行目のように配列のように要素を代入したり値を取得したりする事ができるようになる。
このコードをみてわかるとおり、インデクサの実態はthisプロパティの[]の中に引数を指定する引数付きのメソッド(プロパティ)と言う事ができる。
配列が当然持つべきLengthプロパティは、インデクサでは自動的に定義されない。
Lengthプロパティを使いたい場合は、自前でインデクサクラスにLengthプロパティを実装する。
上記の例は簡単なプログラムを示すための非実用的なものであるが、 はたしてこれが何に使えるかは工夫しだいである。
配列のように表現できるオブジェクトをつくる事により、使い方によっては可読性の良いプログラムをつくる事ができる。
ArrayListクラス等のコレクションクラスは、インデクサを実装する事によってコレクションの要素に配列のようにアクセスできるようになっている。
インデクサの実態は引数付きのプロパティ(メソッド)なので、以下のように通常の配列では実現できないような配列...のようなものを実現できる。
- 添字に負の値を指定できる。
- 添字の範囲に下限,上限が無い。(引数の型の範囲いっぱいまで指定可能)
- 添字の型は整数以外の型を指定できる。
- 複数の引数を指定して多次元配列のようなものも実現できる。
- インデクサはオーバロードが可能。(添字の型や数によって異なる値を返す事ができる。)
つまらない例ばかりで申し訳ないが、このような配列を実装した例を以下に示す。
staticなインデクサは存在しない。
インデクサを使うには、必ずインスタンス化したうえで、使用する。
配列を返すプロパティ
クラスのプロパティを配列として扱うにはどうしたらよいであろうか?
クラスのプロパティにインデクサを実装する事はできないが、 クラスのプロパティの戻り値として配列の値や、インデクサを実装したクラスを返す事はできる。
以下にクラスのプロパティ値として配列を扱う例を示す。
インデクサとItemプロパティ
インデクサを実装すると、隠れたIItemという識別子が勝手に定義される。
そのため、インデクサを実装したクラスにItemというメンバーを定義しようとするとコンパイラーエラーになってしまう。
Itemというメンバーを定義しようとするとエラーになってしまう。
何のために隠れたメンバーItemが定義されているかというと、インデクサーを使う事ができないVC++とかF#等の他の言語からインデクサーにアクセスする場合に、Itemという識別子を使ってアクセスできるようにするためのようだ。
隠れたメンバーItemが定義されているからと言って、indexerSample1[i]の代わりにindexerSample1.Item[0]と記述する事はできない。
このItemという隠れた識別子を、別の識別子に変更する事は可能である。
インデクサの定義に以下のような属性の指定を追加する。
ここでは、Itemの代わりにTheItemを使う事を指定している。
VB.NETではインデクサは「既定のプロパティ」に相当する。(既定のプロパティを宣言する: .NET Tips: C#, VB.NETを参照)
インデクサとインターフェース,多羅尾伴内 七つの顔の男だぜ
クラスに複数のインターフェースを実装して、インターフェースごとに異なるインデクサを実装する事ができる。
異なるインテーフェースに同じシグネチャのインデックスが存在する場合はインーフェース名.thisを使って区別する。
以下にその例を示します。
上記の例では、IndexerInterface1のインデクサを使うと添字の2倍の値が、IndexerInterface2のインデクサを使うと添字の3倍の値が返される事になる。
参考URL