2007-06-12
目次
りんご味Ruby 第5回 藤本 尚邦
■
今回は、初回で提示した簡単なRSSリーダプログラム
require 'rss/2.0'
require 'open-uri'
url = 'http://www.mosa.gr.jp/?feed=rss2'
rss = open(url) { |io| RSS::Parser.parse(io.read, false) }
puts "-- #{rss.channel.title} (#{rss.items.size} entries) --"
puts
rss.items.each { |item| puts item.title }
の3行目
url = ‘http://www.mosa.gr.jp/?feed=rss2′
を見ていきます。単純そうに見えるこの1行ですが、いろいろと深い意味が含
まれています。Rubyプログラマとしての筆者はこの1行を
「MOSAのURLを表わす文字列に`url’という名前を付ける」
と解釈します。もう少し詳しく表現すると
・MOSAのRSSのURLを表わす文字列オブジェクトを生成して
・その文字列オブジェクトに`url’と名前を付ける
となります。「変数urlに文字列オブジェクトを代入する」とは表現しないところがポイントなのですが、それについては後ほど。まず、1番目の文字列の生成の部分を見ていきましょう。
■ 文字列の生成 — 文字列リテラル
Rubyプログラムの実行中には、いろんなところで陰に陽に、文字列が生成されますが、Rubyプログラム中に直接記述できる文字列のことを文字列リテラルといいます。RSSリーダプログラムの3行目「=」の右側には、URL文字列を表わす文字列リテラルが記述されています。
文字列リテラルの記法はたくさんあるのですが、よく使われるものとしては、RSSリーダプログラムの中でも使用されている、シングルコーテーション「’」で囲む記法と、ダブルコーテーション「”」で囲む記法があります。
irb> 'hello, world'
"hello, world"
irb> "hello, world"
"hello, world"
ダブルコーテーション「”」で囲む記法では、文字列リテラルの中にRubyプログラムを埋め込むことが可能です。埋め込まれたRubyプログラムは、文字列が生成される時点で評価され、その結果(を文字列化したもの)は生成される文字列に展開されます。文章で説明するとわかりにくいのですが、以下の実行例をご覧になれば納得していただけるのではないでしょうか。
irb> 'hello, world at #{Time.now}'
"hello, world at #{Time.now}"
irb> "hello, world at #{Time.now}"
"hello, world at Wed Jun 06 11:58:50 JST 2007"
irb> Time.now
Wed Jun 06 11:58:52 JST 2007
ダブルコーテーションを使った文字列リテラルでは、「#{」と「}」で囲まれた部分がRubyプログラム(実行時の時刻を示すTimeオブジェクトの生成)として評価され、結果(実行時の時刻)が生成された文字列オブジェクトに埋め込まれています。また、RSSリーダプログラムの5行目
puts "-- #{rss.channel.title} (#{rss.items.size} entries) --"
では、文字列リテラルにRubyプログラムを埋め込むことによって、その時のRSSのタイトルとエントリの総数を含む表示用の文字列を生成しています。
■ Rubyにおける代入の意味 — オブジェクトのネーミング
Rubyにおける代入は
変数名 = 値
と記述します。見た目はC言語と同じですが、RubyとC言語とでは、代入の意味が大きく異なります。
url = ‘http://www.mosa.gr.jp/’
を、C言語プログラマの視点で解釈すると「文字列オブジェクトへの参照を変数urlに代入する」ということになりますが、Rubyプログラマの視点では「文字列オブジェクトを`url’という名前で参照できるようにする」、さらに踏み込んで
「文字列オブジェクトに`url’という名前を付ける」
と解釈します。なぜ私が「代入」でなく「名前をつける」と表現したいのかというと、その背景には、C言語的な変数入れ物モデルとRuby的な変数名前モデルの違いがあります(どちらのモデルも勝手に命名しました)。
・C言語の変数 — 型ごとにサイズや構造の違う値の入れ物
・C言語の値 – 自分が何ものであるか知らないただのビット列
・Rubyの変数 – 単なるオブジェクト(値)への参照
・Rubyの値 – メッセージに応答するオブジェクト
Rubyの変数は全てオブジェクトへの参照(註 — 実際には、効率のために、変数がオブジェクト値そのものである場合もあるのですが、意味的にはすべて参照だと考えて問題がありません)なので、変数の型の違いを意識した発想で考えるよりも、変数をオブジェクトの名前として考える方がわかりやすいのです。
また、Rubyにおいて型とは、オブジェクトが「どんなメッセージに応答できるか」である、ととらえることもできます(DuckTyping – 後述)
代入・オブジェクト・変数については、スコープ・環境のことをおさえておく必要もあるのですが、今回は書くことができませんでした。最後にしつこく、Rubyにおける代入の要点を繰り返して今回の終わりとします。
Rubyでの代入とは「オブジェクトに名前を付ける」こと
■ おまけ
Rubyの世界では、Duck Typingという言葉がよく使われます。型とは「あるメッセージに対して応答できるかどうか」である、というような考え方です。「ガーガーと鳴いているアヒルのような鳥がいるぞ。ガーガー鳴くのであれば、それがアヒルでも白鳥でも犬でも猫でもバケツでもヤカンでも、たいした問題ではない」と考えるのです。どのクラスに属しているかということではなく、個々のオブジェクトがどう振る舞うかを重視するのです。
今週は何と言ってもWWDCの週ですね。RubyCocoaのセッションなどもあるはずなので、現地でこのメールを読んだ参加者の方はぜひどうぞ。Ruby界では、6/9,10とRuby会議2007が東京で開催されますが(このメールが届くころには終っている)、DuckTypingという言葉の発明者、達人プログラマことDavid Thomasさんのキーノートスピーチがあります。光栄なことに、私もRubyCocoaの話をさせていただくことになっています。自分の発表のことでいっぱいいっぱいではあるのですが、楽しんできたいと思います。
藤本裕之のプログラミング夜話 #116
承前、いよいよ今回は「分割された nibファイル」そのものを作成する。準備はよろしいか? ってあっけないほど簡単なんだけどね。以下に示した手順の通りやればもう小学生でも(アルファベットの区別さえつけば)正しくできてしまうでしょうという代物。
まずは Interface Builderを起動する。他のnibファイル……たとえばXcodeでプロジェクトウインドウ中の nib ファイルのアイコンをダブルクリックするとか、そういうんぢゃなくて直に Interface Builder を起動した場合、「Starting Points」というタイトルのウインドウが表示されてこれから作成する nib ファイルのタイプを選択できる。今回の場合、アバウトパネルを出すウインドウを作るので「Cocoa」の下の「Window」を選べばいい。
選ぶとすぐにウインドウが開いてnibファイルが編集可能になるわけだけ
ど、ここで見慣れた MainMenu.nib とこのファイルの見てくれの違いに着目しよう。MainMenu.nib では、File’s Ownerのアイコンは……これ、なんて呼べばいいのかな、なんつうか「ファインダがオリジナルのアイコンを持ってないアプリケーションを表示するためのアイコン」だよね。これが今作ったばかりの Window用の nibファイルでは単なる Objectを表すブルーの立方体になっている。もう一つの違いは……そう、MainMenuというアイテムがない。
さて、この新しい nibファイルの中身を前回コーディングした内容に合わせよう。覚えているだろうか。我々(…と、また共犯者表現をしてしまった。このテの説明文ではやりがちなんだよね。オレです、オレ)はアプリケーションのプリンシパル・クラス「MyApplication」を記述した MyApplication.h に、aboutWindowControllerというインスタンス変数を宣言した(実は今気がついたけどこの宣言の型名のほう、前回はAboutWindowManager* と間違ってた上、クラス宣言が抜けてました。おまけにMyApplicatio.mにあるべき #import文も足りませんでした。お詫びの上、訂正いたします)。
#import
この「AboutWindowController」というクラスを、この nibファイルのFile’s ownerにしなければならない。第一に「Class」タブを選んでクラス・ブラウザを表示し、 NSResponder のサブクラスであるNSWindowController に新たなサブクラス「AboutWindowController」を作る。作ったら「Classes」メニューの「Create Files For MyApplication」でソースファイルを……え、前回の最後で「もうこれ以上のコーディングは必要ない」って書いたって? まだコーディングしてないでしょうが。これらのファイルはないとエラーがでるから作るんで、別に中身は書き換える必要ないの。
……えっとどこまで行ったっけ? そうそうソースファイルを作ったら、「Instances」タブを選び、File’s Owner を選択状態に、Inspector で「Custom Class」選び、このFile’s Ownerのクラスを今作った
AboutWindowControllerとする。次にこいつの2つ隣にあるWindow をこいつの
アウトレットとして連結し、あとはそのWindowの中身をアバウトパネルとして
ふさわしいものにして、このnibファイルを「MyAbout.nib」という名前で保存
すればおしまいである。
MyApplicationをリンクして実行する。どっか書き間違えたり nibファイルの保存を忘れたりしていなければ、アプリケーションメニューの一番上「About New Application…」(今度のInterface Builderではちゃんと日本語リソースを用意してくれるのかね?)を選ぶと、MyAbout.nib からリソースが読み込まれ、アバウトパネルが表示される。
とまぁ、こんなふうにしてアプリケーションで使う多様なリソースを複数のnibファイルに分割しておける。おじいさんとおばあさんはいつまでも仲良く幸せに暮らしました、めでたしめでたし。
と、これで nibファイル分割の話は終わるはずだったのだが、前回の原稿を送るとき「 nibファイルの分割話もあと1回でおしまいです。次はなにをやりましょうかねぇ」と書いたら、折り返し「サブビューの中身を別 nibファイルに持つというケースについても解説してよ。特にそんなかに配置されたコントロールからどうやってアクションを受け取るとか」というリクエストが……。なぁるほど、言われてみればそれはワタシ、今までやってみたことありませんでしたわ、というわけで次回WWDC明けは「ビューの中身を 別nibから読み込む」というのをやります。請うご期待。
(2007_06_05)
高橋真人の「プログラミング指南」第114回
〜XcodeによるPowerPlant X入門(6)〜
こんにちは。高橋真人です。早速続けます。
次はMyApplication.hです。
MyApplicationというクラスは、最初のプログラム例でも使用したPPx::Applicationというクラスのサブクラスとして定義していますので、まずはPPx::Applicationについて説明します。
PPx::Applicationのクラス定義をしてあるPPxApplication.hを見てみると分かりますように、アプリケーションの中核を構成しているクラスにしては構造はかなりシンプルです。特に、オリジナルPowerPlantのLApplicationクラスと比較してみると、そのシンプルさは顕著です。
これは、以前からお話ししている「PPxの開発期間が短かった」ことも理由の一つだと思いますが、同時に「Carbonイベントを積極的に利用するとコード量が少なくて済む」という要因が大きいと私は見ています。
これも以前からお話ししていることですが、現在のCarbonの仕組みは、APIこそC言語であるものの、設計の背景には所々にオブジェクト指向的な発想が垣間見えます。そのため、Carbonフレームワーク(中でも、CarbonイベントとHIView)の設計意図を汲み取り、うまく利用してやると、C++のようなオブジェクト指向言語と馴染み易い設計ができ、処理の多くをフレームワーク任せにできるため、PPxの側ではそれほど多くを書き込まなくても済むようにできるのです。
従って、オリジナルのPP(PowerPlant)が旧来のMac OSのToolboxを利用してオブジェクト指向の仕組みを実現するために多くのコードを必要としていたのに対し、PPxの場合にはCarbonの仕組みを利用してコードを大幅に削減しているという側面もあるのです。
ところで、単純な構造と申し上げたPPx::Applicationですが、これが継承しているPPx::ApplicationTargetとPPx::Attachableという二つのクラスもかなり単純な作りになっています。
まず、ApplicationTargetの方ですが、これはCarbonイベントのハンドラをインストールする際にApplicationをイベントのターゲットにするためのものです。一般に、Carbonイベントのイベントハンドラをインスールする場合、やり方はすべて同じです。即ち、
・イベントハンドラへのポインタをNewEventHandlerUPP()に渡し、
EventHandlerUPPを生成。
・生成したEventHandlerUPPをインストールするが、その際、イベントターゲッ
トの指定――つまりどのオブジェクトにおいて発生したイベントを処理する
のか――と、処理する対象のイベント(複数指定可)に反応するのか――つ
まり、イベントターゲットに対して、どのイベントが来た時にハンドラを呼
び出すのか――の指定を行う。
という手順です。
つまり、いろんな種類のイベントに対応するハンドラをあちこちに仕掛けておくことで、さまざまなイベントにきめ細かく対応できるわけです。
で、このイベントをインストールするAPIは基本的には一つ、
OSStatus
InstallEventHandler(/*引数省略*/);
というものです。ですが便宜上、以下の6つのマクロ、
/*同様に引数は省略*/
InstallApplicationEventHandler();
InstallHIObjectEventHandler();
InstallWindowEventHandler();
InstallControlEventHandler();
InstallMenuEventHandler();
HIViewInstallEventHandler();
が用意されています。これらは、監視の対象からEventTargetRefというものを取り出し、それと共にハンドラをインストールするという手順、例えばアプリケーション自体をイベントターゲットにする場合であれば、
EventTargetRef targetRef = GetApplicationEventTarget();
IntallEventHadler(targetRef, handlerUPP, ...);
という具合に2ステップで行う必要があるところを
InstallApplicationEventHandler(handlerUPP, ...);
と、1行の呼び出しで済むようになっています。(単に見た目の問題ですが)
しかしながら、PPxではこれらのマクロを使わずターゲットを明示して、すべてをInstallEventHandler()で処理しています。ただ、あくまでもそれはPPx内部での話でして、PPxを使うユーザーが呼ぶのは、イベントを処理する各クラスのInstall()という関数だけです。(この辺は、実際のコードで見ていただいた方が分かりやすいでしょう。実例は間もなく出てきます)
要はPPx::ApplicationTargetというクラスは、このような仕組みを助けるた
めに用意されているものです。
次にPPx::Attachableの方ですが、こちらはオリジナルPowerPlant時代にも持っていたアタッチメントという仕組みを実現するためのものです。アタッチメントというのは、簡単に言いますと、既存のクラスに新たな機能を付加する時、サブクラスを作らずに行える仕組みです。また、機能を動的に付加したり外したりもできます。
ただ、必ずしもPPxのマスターのために理解が必須というものでもありませんので、この連載では解説はいたしません。PPx付属のドキュメントに解説がありますので、興味のある方は覗いてみてください。
さて、MyApplicationはPPx::Applicationに加えてもう一つのクラスを継承しています。CommandProcessDoerというクラスです。
PPxでは、Carbonイベントの処理がフレームワークの担う機能としてかなり大きなものとなっていますが、イベントを処理するためのクラスはすべてEventDoerというクラスから直接・間接に継承したものとなっています。
CommandProcessDoerは、EventDoerの直接のサブクラスでなく、
SpecificEventDoerというクラスを間に挟んで継承されています。即ち、EventDoer→SpecificEventDoer→CommandProcessDoerという継承関係になっています。
詳しい仕組みについて興味のある方は、適宜ヘッダファイルを見て確認していだきたいのですが、C++のテンプレートという仕組みを使っているため、少し難しいかもしれません。以下のように理解していただければとりあえず使うことはできると思います。
EventDoerは汎用のイベント処理のためのクラスで、これは抽象クラスです。このクラスを具体化するに当たり、SpecificEventDoerというクラスとテンプレートによるパラメータを組み合わせることで、特定のイベントクラス、特定のイベントの組み合わせに特化した専用のクラスを定義することができます。
つまり、その専用クラスの一つが、いま話題にしているCommandProcessDoerなのですが、このクラスが定義されているヘッダファイルであるPPxCommandEvents.hを見てみると、
class CommandProcessDoer : public SpecificEventDoer<
kEventClassCommand,
kEventCommandProcess> {
protected:
virtual OSStatus DoCommandProcess(
SysCarbonEvent& ioEvent,
HICommand inCommand,
UInt32 inKeyModifiers,
UInt32 inMenuContext) = 0;
private:
virtual OSStatus DoEvent( SysCarbonEvent& ioEvent );
};
という感じになっています。
このクラスが継承しているSpecificEventDoerのテンプレートパラメータ(<と>で囲まれている部分)を見ると、kEventClassCommandとkEventCommandProcessが指定されていることが分かります。
つまり、CommandProcessDoerは上記のCarbonイベント(kEventClassCommand
とkEventCommandProcessの組み合わせ)を処理する専用のクラスで、このイベントが到達した場合にDoCommandProcess()という関数が呼び出されるということになります。ただし、忘れてはいけないのは、イベントの処理には「ターゲット」という概念がありますので、呼び出されるのはあくまでもこのクラスがインストールされているターゲットに上記のイベントが到達した場合に限られることです。
この辺の仕組みは、また改めて説明します。
ただ、上記のクラス定義を見ると分かりますが、このCommandProcessDoer自体も抽象クラスです(DoCommandProcess()の定義の末尾に=0が付いているので)。従って、このクラスの仕組みを使うためには必ず継承を使うことが必須となります。
ややこしく思えるかもしれませんが、要は、任意のイベントターゲットになり得るクラス(PPx::Applicationとか、PPx::Windowとか)に組み合わせて継承させることで、このイベントの組み合わせを処理できるようになるわけです。
以上をまとめますと、MyApplicationは、kEventClassCommandとkEventCommandProcessの組み合わせのイベント(以下、単に「HICommandのイベント」と呼びます)を処理するアプリケーションのクラスということになります。
書籍紹介 GOOGLE MAPS HACKS
解説担当:高橋政明
GOOGLE MAPS HACKS
Rich Gibson, Schuyler Erle 著
武舎 広幸、福地 太郎、武舎 るみ 訳
オライリー・ジャパン ISBN4-87311-293-1 定価3,045円
先週はStreet Viewの衝撃が大きかったのでこの本を取り上げます。
古い地球儀(大西洋でドラゴンが火を噴いている)が表紙の本の日本語版です。
この本を読んだ時はGoogle Mapsだけで本が一冊書けてしまう事が驚きで、実のところその事への興味も少なからずありました。でもGoogle MapsのAPIを直接使う事のない私でも十分楽しめる内容でした。もちろんURLのパラメータが知りたい場合には本書は確実に役に立ちます。
たくさんの情報が載っていますが、そこは最先端を突っ走っているシステムの解説ですから現状とは一致しない部分もありそうです。(日本語版の出版は2006年7月です)
なお出版社のwebに翻訳者によるサポートページと追加情報へのリンクもあります。サポートページには正誤表があります。
★正直なところこのサポートページの情報も膨大で、これだけでもかなり楽しめます。サポートページはこの本のエッセンスと言えそうです。
199ページにはアップルのキャンパスのサテライト写真が同じ場所のVirtualEarthの写真とともに載っています。(ここのリンクもサポートページにあります)
それにしても地図に衛星/航空写真が加わっただけでも十分に魅力的だったのですが、Street Viewは情報量も見せ方もそして操作性もすごいですね。オライリーからはたぶんStreet Viewに対応した第2版が登場する事でしょう。
ちなみにCNET Japanの情報によると「1648 Charleston Rd」の住所で手を振っている人たちがStreet Viewチームのメンバーだそうです。ざっと60人いますね、ちょっとした会社以上じゃないですか。(Street Viewを見るには言語を英語にしてwebブラウザを起動してください)
http://maps.google.com/maps?f=q&hl=en&q=1648+Charleston
+Rd&sll=37.422935,-122.085013&sspn=0.014212,0.017209&ie=UTF8&ll=37.424878,-122
.
08334&spn=0.028424,0.048494&z=15&om=1&layer=c&cbll=37.420894,-122.084098&cbp
=1,355.755250200965,0.502066528784644,0
Googleの開発力の一端がまさに見える上記URLのStreet Viewは一見の価値ありです。このTシャツを着た人の何人かはWWDCにも参加しているかも知れません。
▼出版社のweb(詳しい目次とサポートページへのリンクが載っています)
http://www.oreilly.co.jp/books/4873112931/
◇MOSAからのお知らせと編集後記は割愛します◇