インタフェイス - みる会図書館


検索対象: 月刊 C MAGAZINE 2000年4月号
20件見つかりました。

1. 月刊 C MAGAZINE 2000年4月号

特集 2 Java の変遷と互換性を探る が特殊なわけではなくて , どんな言語であ っても , あるバージョンで機能拡張が行わ れ , その新機能を用いてソースを記述した 場合には下位互換性が成立しなくなる。プ ログラマならば誰でも承知のことだ。とこ ろが , Java の場合ちょっと気をつけるべき は , ソースレベルの上位互換性が常に成立 するとはかぎらない点である。つまり , あ るバージョンではコンパイル可能であった ソースが , それよりも新しいバージョンで はコンパイル不可能になるケースがあるの だ。それも旧バージョンのコンパイラにバ グがあったからといったことではなく , 後 のバージョンで機能が拡張されたことが原 因で古いソースがコンパイル不能になるこ とが起きるのである。具体的には List5 をご 覧いただきたい。何の変哲もなさそうなプ Fig. 13 JDK 1.1 のインタフェイス Shape の定義 pub lic interface Shape ( ログラムである ( とはいえ , 説明のために かなり作為的にコーディングしているので , インタフェイス Sh 叩 e の本来の意味からす れば明らかにおかしい使い方になってい る ) 。 List5 の問題は , Sh 叩 e というインタフェ イスを利用していることにある。インタフ ェイス Shape は , もともと Graphics オプジ ェクトのクリッピング機能を強化する目的 で JDK 1.1 で導入されたものだ。 JDK 1.0 で は , 描画の際にクリッピング領域 ( 何らか の理由から表示したくない領域 ) を設定す ることは ( メソッド cIipRect を用いて ) できた ものの , 一度設定したクリップ領域を保存 しておくことができなかった。そこで JDK 1.1 では「任意の形状」を表すためのインタフ ェイス Sh 叩 e を導入し , このオプジェクト / / インタフェイス Shape を implements するには , / / このメソッドだけを実装すればよかった。 pub lic Rectang 厄 getBounds ( Fig. 14 SDK 1 .2 のインタフェイス Shape の定義 public interface Shape { 〃インタフェイス Shape を imp lements するには , / / 以下のメソッドをすべて実装する必要がある。 public Rectangle getBounds( public Rectangle getBounds( public RectangIe2D getBounds2D( public boolean contains (double x, d0 厄 y); public boolean contains (double x, double y, double w , d0 曲厄 pub lic bO 引 ean contains ( Point2D p public boolean contains (RectangIe2D て public boolean intersects(double x, d0 面厄 y, do 厄 w, do 面厄 h); public boolean intersects(Rectangle2D て pub ー ic path I に e て atO て getpathl terator ( Aff ineTrans form at public PathIterator getPathIterator(AffineTransform at , double f latness); を用いてクリップ領域を保存したり , あと からまた同じ Sh 叩 e を用いてクリップ領域 を再設定できるようにした。 ところが , JDK 1.1 ではこのインタフェイ スに定義されているメソッドはただひとつ だった ( Fig. 13 ) 。しかし SDK1.2 では , Java 2D パッケージの導入に伴って , このインタ フェイスが大幅に拡張され , オーバロード されたものも含めて合計 10 個のメソッドを 備えることになった (Fig. 14 ) 。 その結果何が起きるかというと , List5 に 示したソースでは , Shape を implement して いるにもかかわらず , 実装を与えているメ ソッドは getBounds だけであるため , SDK 1.2 でコンパイルした場合には残り 9 個のメ ソッドの実装が不足していて , クラス MyN estecCIass は abstruct クラスにならざるをえ ず , そのインスタンスを生成することはで きなくなる。インタフェイスを実装してイ ンスタンスを生成できるクラスにするため には , そのインタフェイスが定義している すべてのメソッドの実装を与えなければな らないことを思い出していただきたい。し たがって , List 5 のソースは SDK 1.2 ではコ ンパイルに失敗する。つまり , SDK 1.2 で は JDKI. 1 に対してメソッドが追加されたた め , それらを実装していない List5 のソース はコンパイルエラーになってしまうのだ このことはべつに筆者の発見というわけ ではなく , JDKI. 1 の API ドキュメントには ちゃんと次のように警告されている。 This interface will be revised in the upcoming Java2D project. ーー中略 Since may su 「 s 0 「 expanded in the future, developers should avoid implementing this interface in their own classes until it is completed in a later release. つまり , 「将来の Java2D プロジェクトに おいてこのインタフェイスは見直される予 定である。ーーー中略ーーこのインタフェイ 特集 2 Java の変遷と互換性を探る 69 るかもしれないので , 開発者は , 後のリリ スは将来拡張されたり置き換えられたりす

2. 月刊 C MAGAZINE 2000年4月号

これは List 1 ~ 4 の例を見れば明らかなよう らのプログラムは , 先に示した List 1 , 2 の に移植性に注意している言語であるとはい え , ある開発環境で新たに仕様変更を受け 例とは違って , JDK 1.0 の言語仕様の範囲 に成立しない。したがって原則としては , 古いバージョンの環境でもコンパイルでき た言語機能やクラスライプラリを利用した でコーディングされていて , 構文的には List るようなソースを記述するのであれば , 新 場合には , そのソースコードは古い開発環 3 , 4 がコンパイルできない理由は見当たら しいバージョンで追加された機能を用いて ない。これらのソースがコンパイルに失敗 境ではコンパイルできない。具体的な例と はならない。それが言語の構文 ( たとえば して , 仕様変更のあった言語機能を使った するのは , JDKI. 1 あるいは SDKI. 2 で新し 内部クラス , 無名クラス , 無名配列 , イン くクラスライプラリに追加されたクラスあ List 1 , 2 をご覧いただきたい。 List 1 では るいはインタフェイスを利用しているため スタンス初期化子 , s ⅲ c など ) であれ , Li JDK 1.1 で導入された無名配列という機能 である。 Java の場合 , ソースのなかで参照 st 3 , 4 のようにあるバージョンから付け を使っているため , JDKI. 0 の開発環境で 加えられたクラスやインタフェイスであれ , はコンパイルできない。また List2 では SDK しているクラスあるいはインタフェイスが あるいはあるバージョンから付け加えられ 1.2 で導入された s ⅲ c というキーワードを コンパイル時に解決できなければ ( 見つけ られなければ ) , コンパイルエラーとなるの たメソッドやフィールドを参照するだけで 使っているため , JDKI. 1 以前の開発環境 ではコンパイルできない ( もちろん , も下位互換性は成立しなくなる。また , 同 だ。 こで s ⅲ c を使っていること自身には深い意味 これらの例の特徴をまとめると , いずれ じ SDKI. 2 というバージョンであっても , J2 はない ) 。 もソースレベルにおいては上位互換性は成 EE に固有のクラスライプラリを利用したソ 別の例として , 仕様変更のあったクラス 立するが , 下位互換性が成立しないサンプ ースは , J2SE の環境ではコンパイルできな いし実行もできない。これは SMI の純正処 ライプラリを用いているために古いバージ ルであった。ソースの上位互換性とは , 古 理系環境にかぎらず , ほかのべンダがリリ ョンではコンパイルできなくなる List 3 , 4 いバージョンの環境においてコンパイルで を示そう。 List 3 は JDK 1.1 以降でなければ きたソースは , 新しいバージョン ( 上位バー ースしている言語環境でも同じである。べ コンパイルできず , List4 は SDKI. 2 以降で ジョン ) の環境でもコンパイルできること ンダ固有のクラスライプラリを利用した場 合 , ソースレベルでもバイナリレベルでも なければコンパイルできない。しかしこれ を意味する。下位互換性はその逆であるが , ほかの環境に対する互換性はなくなる。 ist SDK 1 .2 以降でないとコンバイルできないソースプログラム 2 ソースレベルの上位互換性が c lass List2 { 成り立たない場合 public static VOid main(string[ ] args) { int n = (args.length = lnteger. parseInt(args[O] int k = (args.length く 2 ) ? 2 lnteger. parselnt(args[l] 「古い環境でもコンパイルしたければ , 新 system. out. println( fractions(k) [n] 規の機能 ( それが言語の構文的なものであ れ , クラスライプラリであれ ) を使っては / / strictfp のキーワードは SDK 1.2 で導入された。 static strictfp d0 厄 [ ] fractions(int k) { ならない」とか「べンダ固有の機能を使えば , return new dO 面厄 [ ] { 1.41421356 * k, 1.7320508 * k, 2.1474836 * k, ソースの互換性がなくなる」というのは , い わばあたりまえである。これはべつに Java SDK 1 .2 以降でないとコンバイルできないソースプログラム / / Comparab 厄というインタフェースは SDK 1.2 で追加された。 class MyCaIendar imp lements comparable { String str; MyCaIendar(String s ) { s セて = 町 } pub lic int compareTo(Object 0 ) { return の } public VOid heIIO( ) { system. out.println(str) , JDK 1 . 1 以降でないとコンバイルできないソースプログラム 1 import java. beans. ヨ / / Beans クラスは JDK 1.2 で追加された。 C ー ass MyBeans extends Beans { String str; MyBeans ( string s ) { super( str = 町 } 3 public VOid he Ⅱ 0 ( ) { System. out.println( s して ) 1 class List3 { public static VOid main( string[ ] args ) { MyBeans my = new MyBeans( "he Ⅱ 0 , world" my. hello(); public class List4 { pub lic static void main( string[ ] args ) { MyCaIendar my = new MyCaIendar( "he Ⅱ 0 , world" my. hello(); 68 C MAGAZINE 2000 4

3. 月刊 C MAGAZINE 2000年4月号

ースで仕様が完成するまでの間は , 自分の 性のほうが高くなるのではないかと期待で 位互換性が保証されている。つまり保守リ クラスのなかでこのインタフェイスを実装 リースの間では ( バグに依存している部分 きる。 Java のメリットであるアーキテクチ するのは避けるべきである」と明示されて ャニュートラル性とは , Java の実行環境は を例外として ) , どのバージョンでコンパ いるのである。であるから , いうまでもな すべて同じアーキテクチャであるかのよう イルしたバイナリを , どのバージョンの実 くこれは SMI を責めるべき問題ではなく , に働くことを意味しているはずであり , 行環境に持っていっても正常に動作する。 「避けるべき」とされたことをしているのが れがまったく真実であれば , どんなプログ 一方 , 異なる機能リリース ( 1.1. x , 1.2. x な 問題なのである。ただ , Java の言語仕様で ど ) の間では , バイナリレベルの上方互換 ラムもどんな実行環境に持っていっても動 はこういったことも起こりうることを知る 作するはずである。しかし現実には , この 性は保証されるものの , 下位互換性は保証 ための例としてここで取りあげた。 点についてもそうはいかない。 されない場合がある。つまり , 低バージョ まとめると , ソースの互換性については たとえば , J2SE に付属している「 Java2S ン ( たとえば 1.0. x ) でコンパイルしたバイナ 次のようにいえる。 DK 旧バージョンとの互換性」という文書に リは , 高バージョンの環境での正常な動作 ①コンパイルする環境に応じて , その環 よれば , Fig. 15 に示すような内容のことが が保証されている ( これまた , コンパイラ 境が提供している機能だけを使う。具 記されている。そして一般的な原則として のバグに依存している場合を除く ) が逆に 体的には言語仕様の拡張と , クラスラ は , 保守リリース ( 1.1.1 , 1.1.2 など ) の間で 高バージョン ( たとえば 1.2. x ) でコンパイル イブラリの機能変更について注意する。 は , バイナリレベルの上位互換性および下 したバイナリは , 必ずしも低バージョン ( た Java 2 の A 曰仕様書には「 Since( 導入さ lSt JDK 1.1 だけがコンバイル可能 ( JDK 1 .0 , SDK 1 .2 でもコンバイルできない ) れたバージョン ) 」として表示されてい る ( 場合が多い ) のでこれを参考にする とよい。 ②インタフェイスやアブストラクトクラ スを実装した場合 , 元のインタフェイ スやアブストラクトクラスに対して , 後のバージョンで機能追加が行われた 場合古いソースがコン / ヾイルエラー になる可能性がある ( 上記 Shape インタ フェイスのケース ) 。 ava の バイナリ互換性 次に , ノヾイナリ互換性について調べてみ よう。 Java の特性を考えると , ソースの互 換性よりもバイナリの互換性のほうがはる バイナリの互換 かに重要であるとともに Fig. 15 SDK 1 .2 と旧バージョンとのバイナリ互換性 ①バイナリレベルでの上位互換性は保たれる すなわち , JDK 1 .0 または 1 . 1 のコンバイラが作成したクラスファイルは , SDK 1 .2 の環境で正常に動作する。ただし , JDK 1 .0 あるいは 1 . 1 のコンバイラにバ グが存在していて , それが SDK 1 .2 では修正されている場合には , 動作が変わったり , あるいは動作しなくなる場合もありえる。 ②バイナリレベルでの下位互換性は一般に保証されない SDK 1 .2 で新しく定義された A 曰を使っている場合 , JDK 1 .0 あるいは 1 . 1 の実行環境では動作しない。 SDK 1 .2 で新しく定義された A 曰は使用せず , JDK 1 .0 ま たは 1 . 1 で定義されている A 曰だけを使っている場合 , それそれ JDK 1 ℃あるいは 1 . 1 の実行環境で動作するが , これは完全に保証されていない。コンバイル時に -target 1 .2 を指定すると , JDK 1 ℃あるいは 1 . 1 の VM では動作せず , SDK 1.2 ( 以降 ) の VM 専用となる。 5 import )ava. awt. * ー public c lass List5 { / / Shape は JDK 1.1 で導入されたが、 / / その仕様は SDK 1.2 で拡張されている。 interface I nterface extends Shape { pub lic String whoAreYou ( / / 内部クラス c lass MyNestedCIass implements MyInterface { public string wh0AreYou( ) { return getCIass( ) . getName( 潺 } public RectangIe getBounds ( ) { て eturn new Rectangle( 潺 public List 引 ) { / / 内部クラスのインスタンス MyInterface myClass1 = new MyNestedCIass( / / 上記内部クラスの無名サブクラスのインスタンス MyInterface myClass2 = new MyNestedCIass( ) { / / それぞれのオブジェクトのクラス名を調べる system. out. println( nmyC lassl : 十 myCIass1. whoAreYou( ) system. out. println( "myc lass2 : ″十 myCIass2. whoAreYou( ) public static VOid main( String[ ] args ) { List5 my = new List5( 70 C MAGAZINE 2000 4

4. 月刊 C MAGAZINE 2000年4月号

リンタであれば「印刷する」であるし , FAX ② Service の検索 こういうと難しく聞こえるかもしれない が , 要はお互いに関連するオプジェクトを であれば「 FAX の送受信をする」 , ビデオデ 特定のサービスを利用したいクライアン ネットワーク上のどこかにまとめて格納し ッキであれば「録画する」などがサービスに トは , 共通のインタフェイスを指定して look ておき , それに対して指定した値に照合す up サービスに検索を依頼する。 なる。 るオプジェクトだけを検索して取り寄せる Jini に対抗する技術としては , Microsoft ③検索結果として p 「 oxy を通知 ことができるサービスのことである。これ 社が推し進めている UniversaI plug-and-play を実現するのか JavaSpace 技術である。 がある。しかしこれは Wmdows という , 限 lookup サービスからは , そのインタフェ イスに合致する pro が渡され , クライア ネットワーク上の遠く離れたアプリケー 定されたハードウェアのためだけの OS の一 ントへとダウンロードされる。以後は , ダ ション間で情報を伝達し合うときに , 直接 部に組み込まれた技術であり , ほかのハー ウンロードした pro オプジェクトに直接働 アプリケーション間で RMI(Remote Method ドウェアやほかの OS の上では使えない。そ lnvocation ) を使ってやりとりを行ってもよ れに対して Jini では , Fig. 3 に示すように きかけることで望むサービスが利用できる。 いのだが ( 実行効率の点から考えればこれ ネットワーク層の上にオペレーティングシ こで , インタフェイスは Java の型として がいちばんだろう ) , そうするとお互いに ステム (OS) が位置し , その上に Java 技術が 与えられる。また , ダウンロードする pro インタフェイスが複雑になることと , どち 載り , さらにその上に Jini 技術が載る形にな とは , Windows の世界でいうドライバにほ らかのマシンがダウンしていた場合には通 る。そしてアプリケーションやサービスは かならない。 Ji ⅲを用いることで , あらかじ めユーザ ( あるいは管理者 ) がドライバをイ 信できないというような不都合が生じる。 この Ji ⅲの上に載るのが , アーキテクチャ上 ンストールしておかなくても , 必要に応じ そこで両者の間に JavaSpace のサービスを介 の特徴である。 Java のプラットホーム上に て自動的にダウンロードが行われ , 機器が 在させることにより , インタフェイスは Java 載った技術であるために , その下にある OS Space に対する標準的なものを用いるだけ やネットワーク層とは独立して動作できる。 動作するのである。 なお , Jini の技術をさらに生かすには , 分 でよくなり , またマシンダウンの場合にも 細かく分類すると , Java を利用しているこ 散環境においてパーシステントオプジェク 情報の伝達に支障が生じなくなるというメ とで得られるメリットは Fig. 4 に示すような ト (persistent object) を格納し , お互いに交 リットがある。 JavaSpace 技術は , 実際には ものがあるとされている。これらのメリッ 換し合うようなメカニズムがあると便利で Jini 技術の一部として実装されているが , 分 トを最大限に利用することで , Jini は柔軟 散環境においては , 「ファイルシステム以上 , 性と汎用性を確保し , ネットワーク上をオ ある。 データベース未満」の機能を提供するもの プジェクトが動き回って処理を進めるよう と理解すればよいだろう。 な環境を構築している。 Jini は SMI が提案した技術であるが , SMI J ⅲ i 技術の重要なポイントは , lookup サー 以外にも Java の有用性に着目したグループ ビスと proxy である (Fig. 5 ) 。 が存在し , 基盤技術として採用しようとい う動きが目立つようになった。代表的なも ① Service の登録 のとして , HAVi(Home Audio V1deo lnter Fig. 5 に示すとおり , まずサービス側は operability) , GSM (Global system for Mob 自分が提供しているサービスに対する pro オプジェクトを lookup サービスへと登録す ile Communications) , DVB ( Digital Video Broadcasting) , OSGi ( Open Services Gate こで重要なことは , 実際のサービス る。 を提供するハードウェア ( 図のなかのⅣ ic way lnitiative) などがある。 e ) と pro の間は , そのハードウェアに固有 Fig. 4 Jini のアーキテクチャが利用している Java のメリット の方法で通信しなければならないが , proxy ① Java 技術の上に載ることにより , OS 層以下の環境とは関係なく単一の実行環境が得られる が提供するインタフェイス ( 図のグレーの ②上記①によって , ローカルマシン , リモートマシンの区別を問わず , 単一の型システムを利用できる。 部分 ) は , そのサービスの内容を抽象化し すなわち , 同じ型の表現はどのマシン上でも同じになる た , 共通のインタフェイスとして登録する ③ Java のオプジェクトはシリアル化によってネットワーク上で送受信することができる ④上記③によって , オブジェクトをネットワーク越しにダウンロードして利用できる ことである。もちろん lookup サービスのな ⑤上記④のようにダウンロードしたオブジェクトを用いても , セキュリティシステムによって安全性が かには , ほかのサービスから登録された pro 保証される が複数存在している。 Fig. 3 Jini テクノロジの位置 アプリケーション Jini のテクノロジ Java のテクノロジ オペレーティングシステム サービス ネットワーク層 56 C MAGAZINE 2000 4

5. 月刊 C MAGAZINE 2000年4月号

Pe 月に GUI を Perl といえば , 基本的にはコマンドライ ンべースのツールだという認識が一般的だ CGI での利用に関しても , 基本的には文 字列を出力する形で行われていることは , 使 っている人ならよくご存じのはずだ。 UNIX 環境での管理に Perl を使う場合にも , 通常 はファイルや文字列を扱い , コマンドライ ンを中心に動く。 しかし作るスクリプトによっては , オプ ション指定ではなくユーザインタフェイス , それも GUI がほしくなる。最近では , この インタフェイス構築にプラウザを利用する という方法も増えてきてはいるが , やはり プラウザを使うとインタフェイスとしての 制限が出てしまう。少し細かい制御を行い たいとなると , やはり GUI 部分も自前 , こ こでは Perl で用意したくなることが少なか らずあるはずだ。 Perl/Tk とは何か Perl/Tk は , その GUI インタフェイスを P erl に与えるためのモジュールだ。 Tk は TcI/ Tk の Tk 部分を指し , Tcl の代わりに Perl を使 うのが Perl / Tk ととらえればいい。「入門 PerI/Tk 』はその PerI / Tk に関する書籍で " レ a ming Perl/Tk" を翻訳したものだ。 本書は , Perl / Tk という環境を説明する内 容であり , Perl そのものに関してはある程 度の知識を持っていることが前提となって いる。 perl / Tk に関して説明されている範囲はか なり広く , Per1 / Tk の大半を本書を通じて 知ることができる。とくに , ジオメトリ管 理とボタン , ウィジット , そしてイベント 管理と ,PerI/Tk を使ううえで重要な部分は 『入門 Pe 月灯 k 』 Per レ 石曽模 0 、西中第幸共駅 朝″ ( ド第“ムわ著 第イり - ・リぐノ O'REILLY ・ ISB N4-87311-008-4 オライリー・ジャパン / オーム社 440 ページ , 3 , 800 円 Nancy W sh 著 / 石曽根信 , 西中芳幸共訳 ある以上 , 最新の情報をそのまま反映する が古いということだ。原著がある翻訳書で 本書を読んで明らかに気づくのは , 内容 ュアルといったほうが適切だろう。 初心者も広くカバーするリファレンスマニ る。そういう意味では入門というよりも , すいように細かくていねいに説明されてい レンスとして見ると , 初心者にもわかりや 反面 , PerI / Tk のメソッドに関するリファ ないのはかなり致命的だ。 成品のコードを作り上げる過程がほとんど に , 実際に Perl / Tk を使った具体例となる完 識 , 具体例などの部分が欠けている。とく 入門書として重要な導入部や GUI への前知 ようだが , 「入門」 ( " レ arning " ) というには けを考えると気になる部分はある。厳しい 内容は広く押さえられているが , 位置づ することができる。 み解くことで PerI / Tk の多くの部分を理解 とてもしつかりと書かれており , 本書を読 のが難しいのは仕方のないことだが , でき るかぎり注釈などでのフォローがほしいの は当然といえる。本書では一部の注釈はあ るものの , たとえば現在の最新版のバージ ョンに関しても触れられていないなど , 残 念ながら行き届いたフォローがなされてい るとはいいがたい。 とくに PerI / Tk に関しては , 原著の出版か ら翻訳の出版の間に , Tk4. x から Tk8. x への 移行時期をはさんでいるため , 最新情報が どう反映されているかはとても気になる点 になる。 ただし , 移行において Per1 / Tk はそれほ ど変更の影響を受けないため , 必要以上に 気にすることはないだろう。すべてではな いが , 試したサンプルコードのほとんどは Tk8. x 系の環境でも動作していたし , おそ らく翻訳の段階でも確認が行われているは ずだ。 初心者を視野に入れた 詳細リファレンスとして PerI/Tk は , UN Ⅸ環境はもとより Window s を含めた多くのプラットホームで利用でき るようになっており , 汎用的に利用できる GUI ツールを実現することができる。本書 は , その汎用的なツールを作るうえで重要 な参考書になる。 「入門 PerI/Tk 」は , PerI のことがわかって おり , すでに日常的に利用している人が次 のステップとして GUI を使うという場合に はとても有用だ。 残念ながら , 入門書としてはやや具体的 なプログラム作成例に欠けるものの , 各メ ソッドなどの解説は初心者にもわかりやす いリファレンスになっており , Perl から GUI を扱ってみたい人には重要な書籍とな るだろう。 ・お問い合わせ先 ( 株 ) オライリー・シャパン TEL 03-3356-5227 http:″www.oreilly.co.jp/ ( 株 ) オーム社 TEL 03-3233-0641 ( 代 ) http://www.ohmsha.co.jp/ Cmaga B00kends 161

6. 月刊 C MAGAZINE 2000年4月号

う (List11)0 いよう , 注意してください。人名でも「 W01 たとえばこの JIndex プログラムでは , 語 fgang Amadeus Mozart 」のような 3 語以上 句そのものだけでなく前後の文章も表示し この getReader() メソッドを見てお分か から成る名前は現状のアルゴリズムがスペ てやればユーザの判断の参考になる , とい りのように , 冒頭に英数字のある語句はそ ースはひとっしか認めないので , 残念なが うサービス増強アイデアがありえます。 のままでほば正しくソートされますから元 JIndex が Windows のような OS 教育不在 ( コ らひとつの語句として拾われません。これ の語句を返します。全体または冒頭部分が が「 W. A. Mozart 」とか「 W. Amadeus Mozar ンピュータの基礎教育不在 ! ) のユーザが 片仮名である語句は , それらの平仮名化を t 」みたいになっているとどうでしよう ? 多い環境向けの市販ソフトならば , きっと ユーザが一々入力するのはかったるいです たしかにこれらはピリオド文字を構成文字 こんなインタフェイスサービスも盛り込ん から , katakanaTOHiragana ( ) メソッドを 種に含めたために候補語として拾われるこ だことでしよう。 呼び出して自動的に平仮名に変換します。 とは拾われますが , normaIizeName() メソ でも , UN Ⅸ哲学を学んだ私のような者 ソートという目的のためには , 語句の冒頭 ッドによる語姿の正規化は可能でしよう にとっては , テキスト本文が読みたければ 数文字が平仮名になった程度でまず十分実 か ? メソッドを見てみましよう (List 10 ) 。 別ウインドウを開いて , そこでエデイタか 用になります。 覧のようにこの normalizeName ( ) メソ それら以外は漢字で始まる語句ですか なんかを立ち上げればすむことです。目的 ら , 14 行目で読みのユーザ入力を求めます。 ッドは , 語中のスペースを見つけてその前 の語のある箇所を表示するのなんか , 工デ イタの検索機能でたぶん十分。 JIndex の進 後を反転し , その間にカンマを入れている これはうつかり失敗することもありえる入 だけですね。このアルゴリズムでは「 W. 行と同期して自動的にテキストの今処理中 力であり , またこのプログラムは現状では Amadeus Mozart 」はめでたく「 Mozart, W. の部分を表示するためには , やはり新規の ユーザインタフェイス部品として JOp ⅱ onP Amedeus 」になりますけど , 「 W. A. Moz 狙」 ane ばっかし使っていて , 同じようなダイ プログラミング努力が必要になるでしよう はスペース文字がないのでそのまま返され が , それも JIndex 本体の中に一枚岩的に組 アログばっかし次から次と出て退屈ですか てしまいます。現状ではこんな人名表記に み込むよりは外部からパラメータをもらう ら , 居眠り運転防止のために「ここはちょ 出会ったらユーザが手作業で「 Mozart , っと面倒な場面よ ! 」とビープ音を鳴らす 別プロセスとして作ったほうがすっきり作 W. A. 」というように語姿を変更しなければ とともに , 入力のやり直しをやや認めてい れます。 あるいは JIndex 本体のウインドウに今処 ます。片仮名を平仮名に変換する katakana なりません。でもまあ , プログラムのこ 理中の行番号を表示すれば , 既存のエディ ToHiragana() メソッドを見ておきましよ の部分で少々判断や入力を間違えたからと う (List 12 ) 。 いって , 焦る必要はありません。いずれに タを使う方法が支援されますしプログラミ この katakanaTOHiragana ( ) は何の変哲 しても最終的には , プログラムの出力結果 ング的にも簡単です。この場合ューザは , 工デイタの行ジャンプ機能を利用します。 もないメソッドですが , まず文字列のコン に対する人間の目と手による編集作業が必 テンツを変更する場合は S ⅲ ng ではなく S 要なんですから。 こういった改良アイデアは今後もっと , ⅲ gBu 幵 er を使わなければならない , という いろいろなアイデアを検討することになる Unicode では「スポーツ」の Java プログラマ初心者のための実践サンプ でしよう。今回は話を本題に戻して , 処理 読みが「すぼ・つ」になる の流れを追います。 こに現れています。 ノレがプ さきほど , GUI によるユーザインタフェ modifyWord() を経過したことによって , 次に上級者でもなかなか気づかないと イスの制作は凝りだすときりがないといい 索引に採用する語の最終的な語姿が決定し 思われるのが , char 同士の引き算 (ch-KKd ましたが , 市販の Windows アプリケーショ ⅲ ) という式に付けている ( char ) のキャス ます。ユーザの判断次第では , プログラム ンなんかはどうしても , ひとつのプログラ が最初に拾って表示したままの語姿という トです ( 8 行目 ) 。これはコンパイラ javac が こともあります。 JIndex はこうやって決定 文句を言うから付けた , てなもんにすぎま ムの中でありとあらゆるインタフェイスサ ービスを提供しようとします。しかし Win せんが , なぜ char から char を引いている結 した語に対して今度は同じく handleNew Word ( ) メソッドの 13 行目で , 語の読みを 果を ( char ) にキャストするのか ? Java の dows 95 以降は一応 , UNIX/X Window Sys char は 16 ビットの無符号整数ですが , 引き tem 等と肩を並べる立派なマルチタスク / 取得します。その次の 14 行目で Hashtable マルチウインドウの OS 環境ですから UN Ⅸ の put ( ) メソッドにより , 採用語句 , その 算の結果は負数になることもありえます。 の伝統哲学 : 小さい簡単なものを組み合わ 読み , 出現位置 ( ファイル名と行番号 ) を The Java Language Specification 4.2.2 には 「整数的タイプ ( ⅲ記 types : byte , short, せて必要なタスクを構成する , が適用でき 記録します。語の読みをユーザに入力させ る getReader() メソッドを見ておきましよ int, long, char) に対する数値演算の結果 ます。 C 言語フォーラム 143

7. 月刊 C MAGAZINE 2000年4月号

チビリティは保たれている。 それでは , クラスインスタンス生成式の 構文はどうして変更になったのか , その基 礎となる構文として Fig. 7 に相当する形をベ ースにして考えてみよう。それは「 new クラ ス型 ( 引数並び叩 t ) 」という形式である。そ れに対して , JDK 1.1 で内部クラス ( 含む無 名クラス ) の構文が拡張された。とくに無 名クラスの導入によって , 以下の 2 点の変更 が施されることになった。すなわち , ・ new の直後に指定できるのがクラス型 以外にインタフェイス型も可能になっ た ・無名クラスではクラスインスタンス生 成式において直接クラス本体を指定す る ことである。第 1 のケースでは , 指定したイ ンタフェイス型を implemen したクラス型 として宣言される。したがって new の直後 に指定可能なものが「型名」に変更されてい る。こうした拡張の結果 , クラスインスタ ンス生成式の構文は , Fig. 8 の最初の定義 へと変更されることになった。 内部クラスのインスタンス生成 Fig. 8 の第 2 の定義もまた , JDK 1.1 によっ て内部クラスが導入された結果必要になっ た形式である。 の形式の実例を先に示した List 2 で用 いているので最初にそれを見てほしい。ク ラス List2 の main メソッドの中央付近で , List21nner 型の変数 myln に対する初期化を 行っている部分がある。 こでは「 my. new List21nner(IO, 20 ) 」と記している。これが Fig. 8 の第 2 の形式に相当するものであり , JDKI. 1 から登場した新しい構文である。 この構文では new の直後に記すのは単なる 「識別子」になっている。それは , 内部クラ スの名前のことである。 内部クラスのインスタンスを生成する場 合 , 必ずそれを取り囲むクラスのインスタ ンスを通じて行う必要がある。もう一度 Li 114 C MAGAZINE 20 4 Java フロクラミングリファレンス 詳説 JDK 解体新斟 stl を見ていただきたいのだが , クラス List 1 のフィールド f00 に対して , 内部クラスの インスタンスを生成して初期化を行ってい た。このときには「 new List11nner() 」とい う Fig. 7 の構文に準じた形でインスタンス を生成していて , とくに取り囲むクラスの インスタンスを意識していなかった。しか し実際には , 内部クラスに対するインスタ ンス生成式が評価されるのが , 取り囲むク ラスであるクラス List1 のインスタンス変数 の初期化子であることが重要なポイントで ある。取り囲むクラスのインスタンスが暗 黙のうちに (this が指すオプジェクトとし て ) 仮定されていたため , とくに明示的に 指定する必要がなかったのだ 一方 , List2 においては , 内部クラスのイ ンスタンス生成式が評価されるのは , static メソッドである m ⅲ n の内側である。この場 合には , 取り囲むクラスのインスタンスを 仮定することができない。そのため , 明示 的に取り囲むクラスのインスタンスを指定 して , それに対して new を呼び出すような 形式で内部クラスのインスタンスを生成す る必要がある。それを行っているのが List 2 に示す「 my. newList21nner( ・・・・・ ) 」という 式である。この場合 , my はクラス Lis のイ ンスタンス ( への参照 ) を格納している変数 であり , それを取り囲むオプジェクトとし てクラス List21nner のインスタンスが生成 される。 そしてこのインスタンス生成式を評価し た結果 , List21nner のコンストラクタの内 側で , List2 クラスのフィールドである List 2. this.x と LISt2. this. y を書き換えるのである が , それは具体的には my. x と my. y に相当す る。このため , これらのフィールドの値は , このクラスインスタンス生成式を評価する ことで更新される。 Fig. 6 に示すサンプルラ ンで Before と A れ er の行に表示される値の変 化に注目してほしい。 なお , 「 my. newList21nner( ・・・・・・ ) 」という 式全体は「クラスインスタンス生成式」であ り , したがって「非配列生成一次子」であり , ということは「一次子」である (Fig. 1 ) 。そ のため , 「一次子 . 識別子」の形で「フィール ドアクセス」として利用できるはずである。 List 2 後半の「 my. new List21nner ( 100 , 150 ) . x 」という部分である。 こでアクセスして いるのは my. x ではなく , あくまでこの式の 前半部分「 my. new List21nner ( ・・・・・・ ) 」で生成 した List21nner のインスタンスのフィールド x であることに注意してほしい。ただし , の場合も my を通してコンストラクタを呼 び出しているので , この呼び出しによって my のフィールド x , y の値は更新される (Fig. 6 駈 er2 : の行の出力参照 ) 。 さらに List 2 のその次の部分では , 「 new List2 ( ) . new List21nner ( 300 , 470 ) Ⅸ」という 式によって , 1 ) クラス List2 の新規のオブジェクトを生 成する 2 ) それを通してクラス Lis ner の新規 のオブジェクトを生成する 3 ) そして生成されたクラス L 創 nne 「の オブジェクトのフィールドである x を 参照する という 3 ステップの作業を一気に行ってい る。 ではこの式を構文的に解釈してみよう。 先頭の「 new List2 ( ) 」の部分はまぎれもな く「クラスインスタンス生成式」であって , そしてそれは「一次子」でもある。そうする と「 new List2 ( ) . new List21nner ( 300 , 470 ) 」 という形は「一次子 . new List21nner ( ・・ ということであり , これは「クラスインスタ ンス生成式」の第 2 の形式に該当する。であ れば , 「 new List2 ( ) . new List21nner ( ・・ の部分もまた「一次子」になる。そして「 new List2 ( ) . new List21nner ( ・・・・・ ) . x 」という元 の式は , 「一次子 . 識別子」という形になって いることになり , これは「フィールドアクセ ス」に相当し , ということは結局この式全体 もまた「一次子」に帰着するのである。 さてこの例では , クラス List21nner のイン

8. 月刊 C MAGAZINE 2000年4月号

特集 2 Java の変遷と互換性を探る 互換性が保証されたプログラム ) に対して る。 1.0 から 1.1 , 1.1 から 1.2 への間には , 数 タフェイス , あるいはメソッドの宣言時に 統一されたプログラミングインタフェイス 多くの保守リリースが行われている。たと 修飾子として (public とか abstruct などと同 を提供するものを指す。さらに , Java プラ えば , 1.1 以降は , 1.1.1 から 1.1.8 まで ( さら 様の位置に ) 指定することで , 該当クラス , ットホームは首尾一貫した互換性のある実 に 1.1.7 にかぎっては 1.1.7A , 1.1.7B があっ インタフェイス , あるいはメソッドでは浮 装を実現するために必要な要求事項を満た た ) の保守リリースが行われた。しかしこ 動小数データに拡張表現を用いないことを していなければならない。 Java2 は , 現時 れらはおもにバグフィックスであり , 基本 明示することができるようになった。した 点での最新世代の Java プラットホーム処理 的な機能の変更は行われていない。したが がって , 1.1 , 1.2 の変更点のほとんどが 系である。本稿では可能なかぎりこれらを って , 機能上の大きな変更は 1.1 と 1.2 のリ コア API を中心とするクラスライプラリの SMI の呼び名に従って使い分けるようにし リース時点で行われている。 機能強化と , それをサポートするコンポー ているが , 総称的に使う場合すべてまとめ Java の言語仕様は登場した時点からかな ネントの追加に当てられている。 て「 JDK 系」と表現する場合もある。 り完成されたものであったため , JDKI. 0 が これらの拡張がどれほど大がかりなもの リリースされて以来 , 明白な文法的の拡張 であるかは , 各バージョンの配布ファイル は 2 度行われただけである。もっとも大き のサイズを見ると明らかである。 Win32 版 な拡張が JDK 1.1 が登場した時点で行われ のファイルのサイズは , JDK 1.0.2 ( 1.0 台の TabIe 2 は時系列に登場した仕様 ( あるい た内部クラスの追加と , それに伴ういくつ 最終リリース , 以下同様 ) で約 3.7M バイト , かの仕様変更・・・・・・無名クラスの追加 , イン は処理系 ) を列挙しているが , それを系列 JDK 1.1.8 で約 8.6M バイト , SDK 1.2 Standa スタンス初期化子 , および無名配列の追加 ごとに分類すると Fig. 6 のようになる。 JDK rd Ed ⅲ on では約 20M バイトにも達する。も 系の本流は , , 版を除くと , 過去にメ などである。また SDKI. 2 の登場時点で , ちろんこれは圧縮された形での配布 ( 1.1 以 浮動小数点の取り扱いに対して , ある種の 降はインストーラ内蔵の実行形式 ) である ジャーなリリースが 3 回行われていて , そ ハードウェアがサポートしている拡張表現 し , なおかっドキュメントは別である。 API れぞれ JDKI. 0 , 1.1 , SDKI. 2 である。この の基本ドキュメントを含めた配布ファイル 系列の現在の最新版は Java 2 Standard Editi を利用して実装を行うオプションが与えら のサイズ ( 展開した形式 ) は , それぞれおよ onSDK1.2 ( 実際にはバグフィックスが行 れた。それに関して s c ゆというキーワー われたため , 原稿執筆時点では 1.2.2 ) であ ドが新たに追加され , これをクラス , イン そ 8M バイト , 27M バイト , そして SDKI. 2 Fig. 6 Java の系列とリリース時期 ( バグフィックスリリースは省略 ) JDKI. 0, 1.1 , SDKI. 2 JDK 1 .0 ( 96 / 1 ) ↓ JavaCard APl(96/10 ) JavaCard 2.0 API(98/10 ) JDK 1 . 1 ( 97 / 2 ) PersonalJava 1 .0 ( 97 / 9 ) ↓ PersonalJava 1 . 1 ( 98 / 7 ) EmbeddedJava 1 .0 ( 98 / 1 1 ) ↓ Java 2 Standa 「 d Edition(98/12 ) EmbeddedJava 1 . 1 ( 99 / 1 ) JavaCard 2.1 APl(99/11 ) PersonalJava 1 .2 ( 99 / 1 2 ) Java 2 Enterprise Edition ( 99 / 1 2 ) Java 2 Micro Edition ( 99 / 5 ) 特集 2 Java の変遷と互換性を探る 59

9. 月刊 C MAGAZINE 2000年4月号

リは JDK 1.0 でも正しく動作する。つまり , があったためである。本来 JVM は , List4 の ある限定された条件のもとではソースは互 これらのプログラムはソースの互換性がな バイナリコードをロードした時点で , イン 換だが , バイナリが JDKI. 0 とそれ以降とで い環境に対しても , バイナリの互換性は確 タフェイス Comparable が解決できる ( ライ は非互換になるケースがあることを指摘し プラリ中に存在する ) ことをチェックしなけ 保されているのである。 ておこう。 List7a, 7b, 7c に示すようなプ これに対して , List3 や List4 のようなプ ればならない。 JDKI. 1 の JVM はこのチェッ ログラムを考える。 List7base というクラス ログラムは , 新しいノヾージョンでクラスラ クを正しく行っているので , Fig. 17 に示す でメソッド he Ⅱ 0 が定義されている (List (a) 。 イプラリに追加された機能を利用している そのクラスを拡張して定義した List7sub と ようにエラーになっている。 Comparable は ために , 古いバージョンの実行環境では動 SDK 1.2 からサポートされたインタフェイ いうクラスでも , 同様にメソッド hello を定 作しない。つまり List3 は JDKI. 0 では動作 スであり , JDK 1.1 や JDK 1.0 の実行環境には 義している ( したがって , hello はオーバラ せず , List4 は JDK 1.0 でも 1.1 でも動作しな 存在しないので , JDKI. 1 の動作のように工 イドされることになる ) 。そして List7sub の い。すなわち , List3, 4 にかぎれば , ソー ラーになるのが正しい。ところが JDKI. 0.2 インスタンスを生成し , それに対して he Ⅱ o スの互換性のある範囲でしかバイナリの互 の JVM はこのロード時のチェックを怠って メソッドの呼び出しを行う (List7 クラス ) 。 換性も保証されない。 いて , そのため一見正しく動作しているか こで , 以下の状況を実現するには , 少な なお , これに対してもうひとつ補足が必 のような結果が生じている。 JVM の仕様 くとも List7 クラスのソースファイルと , List 要である。 List 3 のバイナリを JDK 1.0 で動 ( 第 2 版 ) によれば , 実際にはこのチェック 7base, List7sub の両クラスのソースファイ 作させようとすると , 明確にエラーメッセ は行うことが義務付けられるようになった ルとは別のファイルになっている必要があ ージが表示される ( 筆者が実験したところ , が , 実は初版の JVM の仕様ではそれが明記 こでは三つのクラスがそれぞれ別の る。 ちょっとメッセージの表示の仕方が少々怪 されていなかった。そのため , JDKI. 0.2 の ソースファイルに格納されているものとす ・・ (Fig. 16 ) ) 。これは動作しない JVM の実装ではこのチェックを行っていな しいが・・ る。 のが正しいので , 当然の結果である。しか かったようだ。 この場合 , 3 本のソースファイルを同じ し List 4 の実行を試みると , JDK 1.1 では工 ディレクトリに置いておき , JDK の javac コ ラーになるのに対して , 何と JDKI. 0 では一 マンドを用いて List7.java をコンパイルする 見正しく動作してしまう (Fig. 17 ) 。 と , 依存関係から三つのソースがすべてコ しかしこれは JDKI. 0 の JVM の実装に問題 次に , 少々作為的なケースではあるが ンパイルされる。そしてコンパイル後のク ラスファイル List7 を指定して実行すると , コンバイルには JDK 1.1 以上が必要だが , バイナリを実行するだけならは JDK 1 .0 以上であれば可能 クラス List7 の main メソッドのなかで行われ た say. hello() という呼び出しにより , List7 sub の hello が実行されるため , 「 is List 7sub class 」という表示が得られる (Fig. (8) 。 この結果は , JDKI. 0, 1.1 , SDKI. 2 のいず れの環境で実行した場合でも同じである。 さてここで , 何らかの事情から List7sub クラスのソースを修正し , hello メソッドの 定義をコメントアウトして削除したとしよ う (List (d)0 そうすると , 新しい List7sub クラスではメソッド hello を定義していない から , List7base クラスで定義された he Ⅱ 0 メ ソッドが継承されることになる。そして ( こ こが重要なのであるが ) , 修正後のクラス List7sub をコンパイルし ( コンパイラは JDK 1.0 , 1.1 , SDKI. 2 のいずれでもよい ) , ク ラス List7 は再コンパイルをせずに古いノヾイ ナリをそのまま用いたとしよう。クラス List ソースは互換だが バイナリは非互換の場合 St 6 public class List6 { pub lic static void main( string[ ] args ) { List6 ex = new List6( / / インタフェース Cloneable は java.lang に属していて、 / / JDK 1.0 から定義されている。 interface MyInterface extends Cl oneable { pub lic String whoAreYou ( / / 内部クラスは JDK 1.1 で拡張された文法であるため、 / / これをコンパイルできるのは 1.1 以降のコンパイラに限られる。 c ー ass MyNestedC lass impl ements MyInterface { pub lic String whoAreYou( ) { return getc lass ( ) . getName( } public List6( ) { / / 内部クラスのインスタンス MyInterface myC lassl = new MyNestedC lass ( / / 上記内部クラスの無名のサプクラスのインスタンス / / 無名クラスは JDK 1.1 で拡張された文法である MyInterface myClass2 = new MyNestedCIass( ) { / / それぞれのオブジェクトのクラス名を調べる system. out.println( nmyCIass1: 十 myC lassl. wh0AreYou( ) ); System. out.println( nmyCIass2: 十 myC Iass2. whoAreYou( ) 72 C MAGAZINE 2000 4

10. 月刊 C MAGAZINE 2000年4月号

新人応援 モニタ夫会 Ⅵ新春特別企画 新人でなくてもかまいませんので , 積極的にご応募くたさい。 ニタ製品を , 各メーカー様のご協力により提供致します。もちろん , ミングを始める方 , 心機一転して知識を蓄えたい方などを応援するモ も多いことでしよう。そこで C MAGAZINE では , これからプログラ 4 月になり , 徐々に暖かくなってきました。新入生や新社会人になる方 1 FKB8579 キーボード プログラマがもっともよく使うパソコン周辺機器といえ ば , モニタとキーポードではないだろうか ? とくにキー ポードは , キーをたくさん打たなければならないプログラ マにとって重要な周辺機器だろう。 ぶらっとホーム ( 株 ) のキーポード「 FKB8579 」は , そんな プログラマに最適なキーポードである。このキーポードに は「 A4 サイズでコンパクト」 , 「パームレスト付き」 , 「 Sun ワークステーション , Mac (ADB インタフェイス ) , PC/AT 互換機に対応し , それぞれに接続するケープルが標準で添 付」など特徴がいくつもあるが , もっともお薦めしたいの は「キータッチ」と「キー配置」である。 キーはメンプレンスイッチを使い 3.8 ミリのキーストロ ークを実現し , キーの打ちごこちをとても重要視したもの になっている。その感触は , 昔の PC -9801 シリーズや FMV シリーズと似ている。また , キー配置も「新キーは回 キーの上」 , 「キーがキーの上」 , 「電源制御キー ぶらっとホーム株式会社 3 名 夏風概量環環理当員量 新ー : 第を やカーソルキー付き」など , コンパクトなサイズながらよ く考えられた配置になっている。普段使わないキー などについては新キーと任意のキーを同時に打っタイプ にまとめられている。 各分野のプログラマに , ぜひお薦めしたい。 価格 . 9 , 800 円 問い合わせ先 : 03-3251-7000 IJRL : http://www.plathome. CO. jp/ 春の新人応援モニタ大会 7