2008-05-31

ヤングサンデー休刊

1987年創刊で当初は隔週発売だった。 最初は高橋留美子の『1ポンドの福音』が読みたくて買い出したのだったが、『海猿』、『おーい、竜馬』『オーバーレブ』『殺し屋1』『コンデ・コマ』『電車男』など結構いい作品をもっていたじゃない。『マイナス』なんてあまりの過激な表現(いじめられッ子だった反動でドSになった教師が山で遭難して死んだ生徒の人肉を食べるというシーン)に自主回収なんてことも今となっては思い出深い。

今だって、『Dr.コトー診療所』や『クロサギ』なんてドラマ化された超メジャーな作品が連載中なのだ。確かに発行部数を見ると、ものすごい落ちようだ。

1990年 80万部
1995年 68万部
2004年 24万部
2005年 23万部
2006年 21万部
2007年 20万部

2008-05-28

Objective-C関連書籍

Objective-C、それにAppleのApplication FrameworkであるCocoaはマイナーな開発ツールだ。AppleのDevelopers Connectionでは詳細なドキュメントが出ているが、やはりリファレンス的なものが多く、これから学ぼうという人にはなかなか最初はハードルを感じてしまうだろう。

やはりまとまった書籍の解説書や入門書があればと思い探したので入手した範囲で紹介を。
わたしが入手した、またはおすすめなのは以下の4書。

  1. たのしいCocoaプログラミング
  2. 詳解Objective-C 2.0
  3. Programing in Objective-C
  4. Cocoa Programing for Mac OS X (5月28日発売予定)

まず、現在日本語で入手できる書籍では、わたしが探した範囲では『たのしいCocoaプログラミング』くらいしか見つけることができなかった。

たのしいCocoaプログラミング
木下誠
ビー・エヌ・エヌ新社
売り上げランキング: 8579

この本はとてもわかりやすくCocoaでのプログラミングが解説されていて、最初の取っ掛かりとしては最適だ。しかし入門編ということでかなり内容も絞られており、体系的に学ぼうとするとかなり物足りない。また、10.5でXCODEやObjective-Cにも手が入ったが、それの情報が反映できていなかったりする。

Programming in Objective-C
Programming in Objective-C
posted with amazlet at 08.05.27
Stephen G. Kochan
Sams
売り上げランキング: 19756

結局洋書に頼ることになり、最初に入手したのが『[Programing for Objective-C][]』。
この本はCocoaよりも言語としてのObjective-Cに力点がおかれている。これは本書のよい点だ。Objective-Cの解説本だと勢いMacでのアプリケーション開発という観点で書かれていることが多く、説明がCocoaと渾然一体となっている。Objective-C自体については何となくイディオムで覚えながら「そんなものか」となし崩し的に覚えてしまうパターンの人が多いと思うが、これを最初に読んでおくと安心できる。

Objective-C自体はオブジェクト指向的な部分の抜いてしまうとC++と違ってほとんどそのままC言語なので、説明の半分はC言語の説明になっている。あとはObjective-Cのオブジェクト指向的な拡張部分と、それらと切り離せないFoundationフレームワーク、ランタイムも含めた解説が続く。従って、Xcodeなどの説明もなく、サンプルコードもコマンドラインベースのものが中心。おそらく、GCC + GNUstepなどでも動作すると思うのでMacじゃない方でも試してみることができる。

難点はC言語の部分。かなりページを割いているのでマスターした人には怠いかもしれない。わたし自身はかなりの年月純粋なC言語に触っていないので復習には丁度よかったが……

Cocoa Programming for Mac OS X
Aaron Hillegass
Addison-Wesley Professional
売り上げランキング: 64

次にCocoaやXCodeなどについての資料が欲しくなる。購入したのは『Cocoa Programing for Mac OS X』。
まだ今月発行されたばかりの本で、当時は日本のAmazonで扱っていなかったので、USのAmazonで購入(予約となったのでDiscountが結構付いたので安かった)。

この本は一転してObjective-C自体はほとんど前提になっていて、Cocoaをほぼ漏れなくカバーした内容となっている。しかも第3版で出版されたばかりなので、内容も最新のバージョンに対応して刷新されており非常に頼もしい。

しかも、テーマを絞った多くの章で構成されており各章は非常にコンパクトなので、1時間程度で内容を確認しサンプルコードを入力して動作確認し、一通り例題っぽい内容も自身で試してみることができる。サンプルコードもダラダラとコードが掲載されているのでなく、キーとなる部分に絞って掲載されており読みやすい。要点を絞った解説と適切なダイアグラムでほとんどの場合自分でコードを再現できるし、難しい場合は完全なコードをダウンロードできるWebサイトも用意されている。
もっとも、今のところおすすめの解説本だ。

詳解 Objective-C 2.0
詳解 Objective-C 2.0
posted with amazlet at 08.05.27
荻原 剛志
ソフトバンククリエイティブ
売り上げランキング: 200

さて、最後に、今月末にリリース予定の『[詳解Objective-C 2.0]』
以前の版が入手できなかったので内容を確認できていないが、おそらく日本語ではもっと充実した解説書と思われる。先の2冊に加えて買う価値があるかどうか微妙なところだが、どうしても日本語でという方は待ちましょう。

WILLCOM 03

東京ミッドタウンで開催されていた WILLCOM FORUM&EXPOに行ってきた。

Willcom 03

今回はコンシューマー向けの製品ではWILLCOM D4と03が、あとは次世代の通信インフラとしてWILLCOM COREが発表されたばかりだったのでにぎわっていた。

D4はあまり興味がなかったので確認しなかったが、03は直接手に取って操作することができた。
幅はadesとほぼ同じだから長さがかなり短くなっているので、手に取った感覚としては携帯に非常に近くなった。シャープの方の話ではこの短さを実現できたブレイクスルーの一つが全面のイルミネーションキーだそうだ。動的に表示を切り替えることができるこの仕組みによってテンキーとカーソルーなどのスペースを大きく省くことができたという。インターフェイスとしても特徴的なこの機能がインターフェイス要件からでなく「大きさ」という非機能要求から発想された点が面白いと感じた。

機能的にはこれだけの大きさに押さえながら、adesの機能に加えワンセグからbluetoothまで組み込まれているのは驚異的(バッテリーの持ちが心配だが)。Windows Mobileも、世界初の6.1 Classic搭載となる。だがそんな点よりも、やっぱりPC指向だったインターフェイスを携帯ライクに大きく変更されている点が大きい。大きさもそうだし、ランチャーも携帯のイメージに近いものになってきている。かな漢字変換もATOKでなくシャープ系の携帯に搭載されている「ケータイShoin」を搭載している。本体のカラーも携帯のようにカラフルな3色が最初からラインアップされているようだ。

まだ、adesを買ったばかりだが少し心が動く……

2008-05-26

『やがて目覚めない朝が来る』

やがて目覚めない朝が来る

有加という女性が大女優であった祖母との関わりを少女時代から祖母の死までを追想の形で書かれた物語。あくまで有加の視点で彼女の聞いたことだけが語られていく語り口と登場人物のからりとした生き様で切ない内容ながら読後はとても浄化されて清々しい気分になる。

現代では同居する家族が減ってきているので、親以外の大人、特に老人と触れあったり話したりする機会が限られている。わたしは身近に祖母が同居していたのでこの物語の雰囲気はとっても懐かしく思われる。祖母との関係は当然親とのそれとも違ったし、特に大人との触れ合いを避けたくなる思春期にある種大人でない特殊な大人としてつきあえた気がする。

そして、老いと病からは、どこかで弱っていく姿を見ることになり「やがて目覚めない朝」を迎えることになる。命の重みを周りにぶつけるように主張する大人は多い中、どこかで迎えなければならない死を受け入れ、自身の生きた証も他人の中に求めず、静かに老いと死を見つめつつ、それでも淡々と生きている老人の中にある種の美しさを見る。そして、子供時代に見えたことは「生きること」がより大事に思え、自分もそういう大人でありたいと願うようになれた。

そういうことを思い出させてくれる本だった。 

やがて目覚めない朝が来る
大島 真寿美
ポプラ社
売り上げランキング: 80661

2008-05-25

今回は 『Java言語で学ぶデザインパターン入門』 からStrategyパターン。


特に解説なし。

HandクラスのコードがStaticを使用した形でそのままではObjective-Cでは移植しづらかったので、少し修正したがコード自体は汚い。

StrategySample.dmg

マリオカートWii

マリオカートWiiにハマっている。

ついにミラースペシャルカップもクリア。エンディング後の集合写真だ。まだ、50ccクラス以外ではグランプリ評価が☆になっていないコースがたくさんあるので、隠しキャラは残っているようだ。

このゲーム、買うなら「Wiiハンドル」同梱版がおすすめ! というかハンドルなしでどうやれというのか? あのドリフトしながらコーナーをクリアしていく感覚はなんとも麻薬的な快感だ。 この操作感は感覚的にはスーパーファミコン時代からかわらんから、やっぱ任天堂のこういったゲーム作りは凄いねぇ。

しかし、今回は敵がどうしてこんなに意地悪いんだ。 先頭を走っているとトゲゾー甲羅(とにかく先頭のクルマ目指して飛んできて爆発する)は飛んでくる、一旦止まると後ろからスーパースターやキラーでまた吹っ飛ばされる、細い道では必ず体当たりしてきて他人を谷底へ落とそうとする。しかも、みんな俺を攻撃してくるような気がする。150ccクラスになると、非常にイライラしてストレスが溜まり精神が安定しなくなる。そんな中でのミラースペシャルカップまでのクリアは感慨深い。

まだ、先は長い。

マリオカートWii(「Wiiハンドル」×1同梱)
任天堂 (2008-04-10) 売り上げランキング: 3

2008-05-24

CDが出たら

先日深夜にテレビを見ていて、久しぶりに泣けた歌。CD出たら買おう。

2008-05-22

ミュードラ『Lily』

MONKEY MAJIKの楽曲に戸田恵梨香をフィーチャーしたショートムービーで「ミュードラ」と称してiTMSで話題の『 Lily icon』。ゴールデンウィークにアップルストア銀座で戸田恵梨香を迎えてトークイベントをやったらしい。

この戸田恵梨香、『野ブタ。をプロデュース』で亀梨の彼女 上原まり子役で見かけたのが最初だが、なんかよい女優さんになったとしみじみ…… いや、そんなこと関係なく、あまりのいじらしさについポチッと購入。

3話のストーリーになっているが、3話の最後は眼鏡がいつのまにか直ってしまって路上でハッピーエンドでなく、また彼が戸田恵梨香演ずるめがね屋さんに行って彼女にまた眼鏡を選んでもらうというエンディングがよかったんでは? (見てない人には何のことやらですね)

2008-05-21

An Upgrade to TypePad's Compose Screen

When Chris Alden, our CEO, asked for feedback last January about the improvements you wanted to see, many of you sent in fantastic suggestions for to how we could improve TypePad's Compose page. We listened to your suggestions, added functionality from your top requests, and we're excited to announce the new Compose tools are ready for release.

近くTypePadのCompose画面がアップデートされるらしい。
主な変更点は、

  1. Text and Photo Alignment
  2. More Image Options
  3. New Font Control
  4. Open Links in a New Window
  5. Control Your Breaks

まぁ、あれば便利な機能かもしれない。
プレーンテキストで自分でHTMLを書いて投稿しているユーザーにとっては「はぁ?」みたい機能だ。というか、今までなかったのが不思議な機能もある。が、リッチテキストモードで編集している人にとっては便利だろう。しかし、そんなユーザーはとっくにectoなんかを使っているだろうから、こういった機能アップがそういう人に訴求するか疑問ではある。

ただ、説明の中のスクリーンショットで見えているHTMLのコードを見るとスタイルシートを使用しない一昔前のHTMLのコードになっている。こんなコードを吐くのだとすると使いたくないなぁ。

一点だけ、この中では"Control Break"の機能はなかなか面白い。
現状ではTypePad自体の投稿機能を使っても、ectoやMarsEditなどの投稿ツールを使っても、記事の内容が導入部(Introduction)と拡張部(Extended)はフィールドが分かれていた。従ってユーザーは記事を書いている段階で「ここまで導入部で」とか切り分けて入力しなければならなかった。実際このWeblogでも面倒になってほとんど拡張部は使っていない。ところがこの"Control Break"の機能を使えば、一気に書いてしまってからグラフィックで示され導入部と拡張部の区切り記号を上下に動かすことによって後から切り分けることができる。この機能は画期的だと思う。

2008-05-20

Facebook上陸

Facebookが日本でのサービスを開始した。

早速登録しようかと思いきや、「既に登録されている」とエラーになる。 あぁ、よく考えたら以前本国のサービスに登録したなぁ。

Photoshop ExpressでFlickrも利用可能

先日からベータ版を使用しているPhotoshop Expressだが、今回Flickrとの連携もサポートされた。

これでFlickrにアップロードしている膨大な画像が利用でき、Photoshop Expressの強力な編集ツールと連携できることでなかなか強力な組み合わせのサービスになった。Photoshop Express側からFlickrの認証を終えると自身のFlickr上の画像にアクセスできる。作成しているSetはフォルダのように見えている(ただし日本語のSetについては正しく名前が表示されれない)。ここからドラッグしてLibyraryに画像を落としてくると編集が可能となる。同様のドラッグ&ドロップでFlickrへの画像の書き出しも可能だ。

今回同様に以下のように埋め込み方式のスライドショーがサポートされた。

2008-05-19

SUBARU EXIGA ティザーサイト公開

ついに6月17日のデビューに向けてEXIGAのティザーサイトが公開された。

なんとワクワク感のない車なんだろう。家族が多くてそういうニーズがある人にはうれしいんだろうか?

それにしてもFlashを使いまくった重たいサイトで、なかなかじっくり見る気がしない。昨年モーターショーで見て以来のいやな予感がさらに強まる。

2008-05-18

Forester Nature Project #1

Forester Nature Project抽選で招待いただけたので行ってきた。

渡良瀬エコビレッジで綿についての説明や昭和初期の珍しい綿繰機(綿から種を取り除く手動の機械)などを見せてもらい、そのまま畑に行ってパラパラと種を蒔いた。蒔くときの密度が問題らしいが、蒔いているうちにだんだんわからなくなり最後は適当に……

お昼に野菜中心の有機食材を使った食事をいただき、渡良瀬遊水池へ。
遊水池までフォレスターを試乗させていただいた。レガシィに乗り馴れていると車体がかなり大きいので重さを感じるが、SI-Driveが付いていたのでS#モードにするとそんな重さも感じさせないくらい元気になる。AT4速だけれど、そうは感じさせないほどスムーズ。聞けばロックアップを賢く行っているので、6速に近い制御だそうだ。

遊水池は、「よくぞ、こんな広大な土地を洪水防止目的で」と驚く。実際は足尾銅山の鉱毒対応だったらしい。 遊水池化で廃村となった谷中村の後などが残っていてなかなか歴史を感じさせてくれるとともに、広大な土地に見渡す限りヨシが茂っていて鳥や昆虫もたくさん見られ、自然を満喫できる。土壌に銅など鉱毒物質が満載なのも忘れてしまうくらい。

Forester Nature Projectのほうはこの後も何回か企画されており、継続して今回蒔いた棉畑を見ていくようなので機会があれば参加したい。責任を取る意味でも(笑)

写真集へ

2008-05-17

Objective-CでUnit Test

XCodeにはUnit TestのFrameworkであるSenTestingKitが添付されている。SenTestingKitでのテスト方法を簡単にまとめておく。

以下のようなクラス Circleがあった場合、

#import <Cocoa/Cocoa.h>#define PI (double)3.14159
@interface Circle : NSObject {
double _radius;
}
+(id)circleWithRadius: (double) raidus;
-(id)initWithRadius:(double)radius;
-(double)diameter;
-(double)dimension;
-(double)circumference;
@property(readwrite) double radius;
@end

まず、テスト用の新規ターゲットを作成する。このときアシスタントで「Cocoa」のカテゴリーから「Unit Test Budle」を選択しておく。名前は何でもよい"TestCircle"などとしておく。

次にFrameworkの取り込みを行う。
Frameworkの定義は、/Developer/Libary/Frameworks/SenTestingKit.frameworkにあるのでこれをプロジェクトに追加する。ここで、先に作成した新規ターゲット"TestCircle”に追加する。

そしていよいよテスト用のコードの追加。
新規ファイルをプロジェクトに作成し、ファイルの種類を「Objective-C test case class」を選択する。ヘッダーフィアルを見るとSenTestingKitのヘッダーのインポートとクラスのテンプレートができているので、ここにテストしたいクラスのインスタンスとテスト用のメソッドを定義しておく。

#import <SenTestingKit/SenTestingKit.h>
#import "Circle.h"

@interface CircleTest : SenTestCase {
Circle* circle;
}
-(void)testDiameterValue;
-(void)testCicumference;
-(void)testDimension;
@end

これらのメソッドのほかにSenTestCaseで定義されているsetUpとtearDownの2つのメソッドを通常はオーバーライドする。それぞれ初期化とテスト終了時の後始末を担うメソッド。その他のテスト用のメソッドに関しては、メソッド名を「test」で始めること。

テスト用メソッドでの確認方法は、SenTestingKitが提供するチェック用の関数を使って以下のように実施する。

-(void)testDimension {
STAssertEquals([circle dimension],(30 * 30 * PI),nil,NULL);
}

この関数では最初の引数と2番目の引数が正しくなければエラーとなる。その他いくつかの関数が定義されているのでそれらを使用してクラスのテストケースとその結果をチェックするロジックを作成する。

これらのチェックはビルド時に行われる。チェックするにはアクティブターゲットをテスト用に作成したターゲット(ここではTestCircle)を指定してビルドする。結果が正しければ何事もなくビルドは完了する。エラーがあれば、ビルドの後以下のようにコンパイルのエラーと同様に表示される。

Download

2008-05-16

Legacy STI - S402

先日マイナーチェンジしたばかりのレガシィだが、STIチェーンのS402が登場した。

S402には、私たちの考える究極のグランドツーリングカーの姿があります。速く、快適に、安全にドライブイングを愉しめるクルマとして進化を続けてきたレガシィ。その味わいを至福の歓びにまで高めるため、私たちは最高と思えるものすべてを投入いたしました。

インターナショナル・エンジン・オブ・ザ・イヤー部門賞受賞を受賞したばかりの2.5L Turboのエンジンを、更に専用のターボ、ECU、排気システムを導入し、サスやブレーキもワンランク上の専用のものを奢り、タワーバーやロアバーでボディ剛性を上げ、これまた専用のエクステリアとインテリアで固めた限定車。

写真を一見したところ、それほど派手な印象ではない。ボディサイドのフロントタイヤ上部にあるスリットがポイントとして目につくくらいだろうか。フェンダーも20mm近く拡大している模様なので、きっと実物は迫力あるだろう。このエンジンを6速マニュアルで最高にチェーンされた足回りで楽しむこの贅沢を味わってみたいものである。

乗り出しで600万円かぁ……

2008-05-15

Objective-Cの手習い:Bridgeパターン

今回は 『Java言語で学ぶデザインパターン入門』 からBridgeパターン。

一応クラス図を載せておく。

ほとんど書くこともない。
今回もプロトコルを使うという手もあったが、普通のクラスにしてからメソッドを作って抽象クラスを表している。

コード見てくださいな。
Download Site

2008-05-14

『ザ・ビートルズ/リメンバー』

クラウス・フォアマン…… 僕にとっては1974年と1994年の2度にわたる奇跡の主人公となったジョージ・フォアマンよりなじみ深い人だけれど、でもそれはどちらかというとビートルズのスタジオ実験的な意欲作『リボルバー』のジャッケットデザイナーとしての彼の印象が強い。最近では『アンソロジー』のイラストを手がけたりもしてる。

ハンブルク時代からの友人という知識はあるが、その頃のビートルズの周辺の人物としてはアストリッド・キルヒヘル、スチュアート・サトクリフとかのほうが何故か印象に残っている。クラウス・フォアマンがマンフレッド・マンというバンドでベースをやっていたことや、その後ジョンやジョージのレコーディングやコンサートに参加していることは知っていても、あまりあのイラストレータと関連づけて考えたことがなかったのかもしれない。

この本は、友人としての思い出を5年以上の連載として綴ったもの。ハンブルク時代から解散後の2005年の『"ジョージ・ハリスン & フレンズ コンサート・フォー・バングラデシュ 』の発売イベントまでの思い出がカバーされている。びっくりするような暴露話や秘話が語られているわけではないが、ポツポツと綴られる思い出は友人らしい気遣いを見せながら等身大のFAB4を描いていて読んでいて楽しい。

"リボルバー" (ザ・ビートルズ)を聞きながら……

2008-05-13

スピードマスターと革バンド

ここ数日暑い日が続き汗をかいたような気がしたので、久しぶりに時計のバンドを外してじゃぶじゃぶと水洗いした。ついで、購入して長らくほったらかしにしていた皮バンドを時計に合わせてみる。

Omega Speedmaster and BUND military BandOmega Speedmaster and BUND military Band

これは昔アンティークショップか何かで購入した正規ドイツ軍(BUND)のNATOタイプの革バンド。見る限り「BUNDタイプ」と呼ばれるレプリカとほとんど変わらないんだけど結構なお値段だった。もったいなくてまだ一度も使ったことがない。時計の下部にもバンドが回り込んでいて重厚な感じ。正規品は19mmしかないが、これが丁度スピードマスターのラグ幅にぴたりとハマる。

Omega Speedmaster and Omega Band

こちらは、以前持っていたオメガの30mm用にと購入したオメガ純正の革ベルト。ベルト幅が18mmなので、スピードマスターにはちょっと細く頼りない雰囲気になる。やはりあの30mmは手放さなければよかった。とってもきれいなムーブメントで時計の雰囲気も良かったのだが、だんだん扱いとか維持とかに神経を使うようになってきて疲れてしまって転売したのだった。

2008-05-12

「聖火ランナーのツィイーに非難が噴出?」

このほど北京五輪の聖火リレーでランナーをつとめたチャン・ツィイー(章子怡)について、大きなダイヤの指輪をはめていたことから、非難の声が上がっている。新華網が伝えた。

[From 「婚約指輪」きらめかせ登場、聖火ランナーのツィイーに非難が噴出!—中国(Record China) - Yahoo!ニュース]
聖火リレーが聖なるイベントでそんなところにアクセサリーをつけてきて不謹慎とかいう理由らしいが、この聖火リレーというイベントが長野でやったあれと同じイベントだとすると中国の方が観光バス数台で乗りつけてなさった所行に比べればむしろ**婚約指輪のほうが神聖**だと思う。

ATOK2008 + 共同通信社記者ハンドブック辞書

今年のATOK2008へのバージョンアップは見送ろうと決めていたのだけれど、つい購入してしまった。

使用していたSKKはわたし的にはとっても満足だったのだけれど、

  1. 小指を酷使するせいか左手がメールを打った後などかなり疲れて腱がつりそうなことがある。
  2. SKKのほうが誤変換で思考が中断されることなく気持ちいいのだが、結局都度文節と仮名送りと変換結果を確認しながらタイプしているようで実際にはタイプが遅くなっていることにチャットをやっていて気がついた。

で、ATOK2008のダウンロード版とハンドブックの改訂版の内容に合わせてハージョンアップした共同通信社記者ハンドブック辞書を合わせて購入。

今回のバージョンアップで歌われている変換精度の改善が本当か、例であがっているサンプルでチェック。

請求書の支払い日時近く市場調査を行うその後サイト内で昨年に比べ高い水準だ昼一までに書類作っといてねそんな話信じっこないねはじめっから持ってけばいいのに熱々の肉まんにぱくついた

完璧!

改善された点として、英数字の変換候補が表示されるとき見てもどれが半角なのか全角なのか区別がつかなかったが、今回のバージョンから候補の横に半角か全角かなど文字種が表示されるようになった。メールなどで全角、半角の統一が崩れていると気持ちが悪いわたしにとっては改善は非常にうれしい。これと合わせて共同通信社ハンドブック辞書と合わせて、精度の高い日本語が打てそうな気分になる。

また、今回ATOKダイレクトなる機能が追加された。
ATOKのフロントエンドにしてアプリケーションを呼び出し連携させようというものだ。インストールされているアプリケーションとの連携はどうということもないが、「はてな」やYahooをサポートするモジュールが公開されていて興味深い。入力した言葉をこれらのサービスを使用してネット上で検索や連想をシームレスに行えるというのは一見便利そう。

ただ、インターフェイスがまだ練れていないので、ATOKダイレクトモードの起動とかそれらが表示する候補の選択などのキーバインドをまた覚えなくてはならないしモードも意識しなければならない。自動検索もできるが、ネットにアクセスしているので一呼吸待たされる感じでとても常用しようという気にはならない。また、検索したいだけなのに結局それらがタイプされてしまうというのもなんだかなぁという感じ。まぁ、今のところ客寄せパンダ的なものだが、これからWebサービスとの連携が増えて行きば、Imput Methodを利用した新たなサービスの形態としておもしろくなっていくかもしれない。

2008-05-11

Objective-Cの手習い:AbstractFactoryパターン

今回は『Java言語で学ぶデザインパターン入門』からAbstractFactoryパターン。

AbstractFactory

クラス数が多いのでクラス図を示しておこう。

とりあえずAbstract Factoryとは……
協調して働くセットのオブジェクトをまとめて作製するためのインターフェイスをプログラマーに提供するパターン。プログラマーは抽象クラスであるFactoryの具象クラスを何らかの方法で得て、その抽象的なインターフェイスを通じてセットのオブジェクトを生成する。

今回もほとんどそのままの移植で、Objective-Cらしいところはあまりない。
唯一Objective-Cに依存した部分は、Factoryクラスの具象クラス生成部。『Java言語で学ぶデザインパターン入門』ではJavaのClassクラスを使用して生成しているが、Objective-CではNSClassFromString関数を使用してClassクラスのインスタンスを生成し、そこからFactoryの具象クラスのインスタンスを生成する。


           Factory* factory = nil;
           Class factoryClass;
           factoryClass = NSClassFromString(classname); 
           if(!factoryClass) {
              return nil;
            }
            else {
              factory = [[[factoryClass alloc] init] autorelease];
              return factory;
            }

JavaのコードのようにExcetionを拾っていないので、呼び出し側で対処する必要がある。どうもObjective-CではExceptoinを積極的に使用していこうという思想ではないようだ。プログラマが考えよってことらしい。
今回はクラスが見つからない場合nilがかえるので呼び出し側では


        factory = [Factory factoryFromClassName:className];
            if (!factory) {
                printf("Class %s is not found.\n",argv[1]);
             }

としている。

参照:Foundation Framework Reference

2008-05-10

Objective-Cのメモリー管理

最近はJavaをまずプログラム言語として始める人が多いだろうから、Objective-Cを使いだした際メモリー管理でつまずくことが多いだろう。わたし自身もすっかりJavaな人になっていたので同様に最初のころハマった。一応メモリー管理についてまとめておこう。

Objective-Cでは10.5からは今時の言語っぽくGabage Collectionが導入されので、Java同様あまりメモリー管理を気にする必要はなくなった。だが、パフォーマンスの問題からなのかXCodeのデフォルトの設定ではオフになっていたりするので、一応レガシィなメモリー管理のお手前も知っておこう。

リファレンスカウンタ、retain/release

さすがに大昔のC++のようにnew/deleteで自身で管理ということはなくて、リファレンスカウンタという割と一般的な手法でメモリー管理はなされている。これはある変数について参照が増えるたびにカウントアップ、参照がなくなるごとにカウントダウンしていき、参照カウンタがゼロになった時点でオブジェクトが削除されるという管理方法。Objective-Cの場合、この仕組みが言語でなくCocoaのライブラリレベルで実現されている。

リファレンスカウンタは生成時点で1に、その後 retainメッセージを送るごとに一つ増え、releaseするごとに減る。オブジェクトにretainCountというメッセージを送ると現在の参照カウンタを返してくれる。以下のようなコードでテストすると、


    ObjectA* objA = [[ObjectA alloc] init];
    ObjectA* obj_copy;
    NSMutableArray* array1 = [NSMutableArray array];
    printf("After initializing        : %i\n,[objA retainCount]);
    obj_copy = objA;
    printf("After assignment          : %i\n,[objA retainCount]);
    [objA retain];    printf("After retain              : %i\n,[objA retainCount]);
    [array1 addObject:objA]; 
   printf("After adding to array     : %i\n,[objA retainCount]);
    [array1 removeAllObjects];
    printf("After removing from array : %i\n,[objA retainCount]);
    [objA release]; 
   printf("After release             : %i\n,[objA retainCount]);

結果は、

    After initializing        : 1
    After assignment          : 1
    After retain              : 2
    After adding to array     : 3
    After removing from array : 2
    After release             : 1

となる。
生成した際にリファレンスカウンタは1になる。別の変数に代入した際にリファレンスカウンタを増やしたければ代入するだけではだめで明示的にretainをかけてやる必要がある。NSMutableArrayに加えたときリファレンスカウンタが増えるのはオブジェクトを集合に追加する際retainをかけてくれているから。Cocoaで提供されているコレクションフレームワークは内部でretainをかけており、removeする際releaseをかけているので注意が必要だ。

AutoreleasePool

しかし、こうやってすべてのオブジェクトを管理するのは面倒だというので、AutoRelasePoolという仕組みが用意されている。このプールにオブジェクトを登録しておけば、リファレンスカウンタに関係なくプールが存在する間はオブジェクトのインスタンスも保証され、Poolの削除とともにオブジェクトも破棄されるという仕組み。Cocoaのクラスはこの仕組みが前提になっているケースが多いので、Foundationのクラスを使うターミナルのプログラムでも以下のようなコードがメイン関数に追加されている。

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];    // User code    ObjectA* objA = [[[ObjectA alloc] init] autorelease];    .....    [pool drain];

このように プールを作成しオブジェクトにautoreleaseメッセージを投げることでプールに登録することができる。オブジェクトはプログラムでreleaseせずとも[pool drain]で破棄される。仕組み的には[pool drain]で登録されたオブジェクトに一斉にreleaseを投げているだけのようだ。逆に言うとプールに登録したオブジェクトといえど、リファレンスカウンタで制御されていてretain/releaseの回数のつじつまはあっていなければならない。「リファレンスカウンタに関係なく」と書いたが、実際にはプールに登録したオブジェクトに関しては「プログラム上でリファレンスカウンタに関係してはならない」が正解か。

また、NSAutoreleasePoolは複数生成することができる。


    NSAutoreleasePool* pool1 = [[NSAutoreleasePool alloc] init];
    printf("Pool1 is created\n");
    ObjectA objA = [[ObjectA alloc] initWithString:@"objA"];
    [objA autorelease];    printf("Pool2 is created\n"); 
   NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init];
    ObjectA objB = [[ObjectA alloc] initWithString:@"objB"];
    [objB autorelease];    printf("Pool2 is drained\n");
    [pool2 drain];    printf("Pool1 is drained\n"); 
   [pool1 drain];

結果は

    Pool1 is created.    Pool2 is created.    Pool2 is drained.    objB is released.    Pool1 is drained.    objA is released.

つまりオブジェクトは直近に生成されたプールにより制御される。一つのプールに依存すると、プログラムが終了するまで多量のインスタンスを抱えることになりかねない。多くのメモリーを消費するクラスや多量のインスタンスを生成する処理では、対象のインスタンスを使用するスコープでNSAutoreleasePoolを生成し不要となったら破棄するのがベター。

Objecitve-Cにおけるretain/release/autoreleaseの方針

実は、このAutoreleasePoolがあるので最初にObjective-Cを書こうと思ったときこのメモリー管理で訳が分からなくなる。上記は簡単な例で説明したが、通常はオブジェクトはインスタンス変数に別のオブジェクトの参照を持っておりそれぞれのライフサイクルが異なっているのは普通で、しかもそれぞれ自身でretain/releaseをかけていたり、AutoreleasePoolで管理されていたりと管理方法もバラバラになってしまう。で、結局retain/releaseのバランスが崩れて、二重解放してしまったり解放されないオブジェクトができたりする。

いくつかの実験とWebサイトなどの情報をまとめると、以下のような方針がよいようだ。

  1. 自身が生成したオブジェクトは自分で解放する。つまり、alloc-initでオブジェクトを生成したメソッド、またはクラスは自身の責任はreleaseをかけるか、生成時にautoreleaseを投げておく。
  2. CocoaのFrameworkでは、クラス名が先頭についた生成メソッドはautoreleaseがかかっている。例えば、NSArrayにおける+arrayWithObjectsや、NSStringにおける+stringWithCStringなど。これらについては、積極的にこれらの生成メソッドを使用しalloc - init***で生成しない。
  3. 同様に自作のクラスについては、CocoaのFrameworkに習いなるべく+クラス名の生成メソッドを用意しその中でautoreleaseをかけるなどして、自身のオブジェクトのライフサイクルに関しては自身で責任を取る。
  4. インスタンス変数については、そのオブジェクトの由来に関わらずretainをかけ、deallocの中でreleaseを入れる。こうすれば、例えばAutoreleasePoolに登録されているオブジェクトでも辻褄は合う。
  5. 局所的に多量のインスタンスを生成する場合(特にループ内など)は、全体のNSAutoreleasePoolの制御に任せるとメモリーをどんどん消費していくので、大量の一時的インスタンスを生成するようなメソッドやループ内ではローカルのNSAutoreleaseaPoolを適用する。

 

2008-05-09

Objective-Cの手習い:Builderパターン

今回は『Java言語で学ぶデザインパターン入門』からBuilderパターン。

クラス数が多くなってきたのでクラス図を示しておこう。

今回のパターンのクライアントであるメインメソッドで、Directorクラスを生成する。このDirectorクラスを使いながら、抽象クラスであるBuilderクラスを通してTextBuilderとHTMLBuilderを利用する。Javaのサンプルではコマンドラインからの引数でどちらのBuilderを使用するかを決定するようになっているが、今回は両方を生成し実行するようにしている。TextBuilderのほうか結果をコンソールに、HTMLBuilderのほうはGreeting.htmlというファイルに結果のHTMLを書き出すようになっている。

今回の実装もほとんどJavaのサンプルコードそのまま。ただし、getResultメソッドに関しては、Objective-CのProperty機能を使うことにした。

まず、抽象クラスであるBuilderクラスのヘッダーでの宣言を以下のようにする。

@property(readonly) NSString* result;

結果を戻すだけなので属性をreadonlyとし、結果はNSStringで戻すこととした。戻す内容はTextBuilderとHTMLBuilderで異なるのでBuilderクラスでのImplementation部での宣言は

@dynamic result;

として、実行時に子クラスでオーバーライドされることを明示する。

TextBuilderではresultに結果のテキストそのもの返すため、結果を格納するNSStringのオブジェクト_bufferを定義し、

    @synthesize result=_buffer;

としてプロパティresultと関連付ける。これだけでTextBufferにresultというメッセージを投げるとメソッドの定義なしで_bufferの内容を返してくれる。

HTMLBuilderでは結果については、

    [_buffer writeToFile:_filename atomically:YES 
            encoding:NSUTF8StringEncoding error:NULL];

としてファイルに書き出し、resultでは_filenameを返すようにする。

参照:Objecitve-C 2.0 Programming Language

鳥居みゆき:『ハッピーマンデー』

結婚していたことを突然DVDの発売イベントでカミングアウトした鳥居みゆきだが、わたしは去年の年末からハマっている。そのDVD『ハッピーマンデー』もしっかり予約で買いましたが、何か?

鳥居みゆき ハッピーマンデー
Victor Entertainment,Inc.(V)(D) (2008-04-23)
売り上げランキング: 53

ある意味でこのDVDは、お笑いという枠を飛び越えてしまっている。
内容的にはテレビでの鳥居みゆきを想定しているとかなりそこから外れているだろう。単にネタを集めたお笑い芸人のDVDにとどまらず、よし悪しは別にして一つの作品として制作するという意図が見える。

同じネタでもテレビでのテンションと違うという意見があるようだが、観客を前にして演じるのとDVDというメディアを通して演じるのではネタの位置づけが異なっていて自ずと演技が違ってくるのも作品としてみると自然なことだと思う。「同じネタじゃん」って批判に対しても、それでも楽しめる「作品」と思う。

もちろん、テレビでは演じられないネタも入っている。しかし、テレビでできない過激なネタ満載という訳ではない。そんなを期待しても、過激なネタはしっかりモザイクとピー音入りで収まっているのでどんなネタなのかさっぱりわからない。たしかに以下のようなネタは、DVDであっても世に出せまいが……

全体のほうは予告編でも見て想像してみてくださいな。ほとんどこの予告編からはDVDの内容について想像はつかないが、雰囲気はよく出ている……

あぁ、なんで買ってしまったのだろう。
ブラックなネタを薬物中毒、知的障害、統合失調症的なキレ気味のキャラで演じ(?)、そこに言葉遊びを絡めていくのが彼女のパターンになっているが、個人的にはその言葉の選び方や連想のつなげ方にハマる。

結局は視聴者を選んでしまうDVDかもしれない。
わたしは誰にも勧めないけれど、しばらくはこっそり一人でこの作品を楽しむだろうし次の作品も発売されればきっと予約で買う。

2008-05-08

地震

午前一時過ぎから頻繁に地震。 震源地は茨城県沖( 北緯36.2°、東経141.7°)で震度はせいぜい2程度…と思っていたら、今度の揺れはかなり来た。千葉の震度はまで発表されていないが、宮城県などでは震度4まで行っている。また、あるかと思うと眠れん。 (追記): 気象庁の記録では一番揺れがひどかった01:4901:54の記録で、千葉のうちの近所だと震度3だな。揺れで駐車場の車のセキュリティの警報が一斉に鳴っている。

2008-05-07

Objective-Cの手習い:Prototypeパターン

今回は『Java言語で学ぶデザインパターン入門』からPrototypeパターン。

ほとんどそのままの移植だが、ポイントは例ではJavaのjava.lang.Cloneableが使用されているが、Objective-CではFoundationに用意されているNSCopyingプロトコルを使用すること。

NSCopyingはオブジェクトのコピーするcopyメソッドを実現しているプロトコルだ。NSObjectでも宣言されているが、内容は空なのでここではあらためて抽象クラスであるProductクラスでも宣言しておく。このプロトコルを実装するにはcopyWithZoneを実装すればよい。ここでは子クラスに依るので、Productクラスでは内容は空。実際のProductクラスの実装クラスのMessageboxクラスでは以下のような実装となる。

-(id)copyWithZone:(NSZone*)zone
{
     id copyDestination = [[[self class] allocWithZone:zone] 
                                    initWithChar:decochar];
     return copyDestination;
}

今回のクラスはインスタンス変数もプリミティブなintの変数を一つ持っているだけなのでこの程度でOk。『Java言語で学ぶデザインパターン入門』では専用のcreateCloneというメソッドを定義しているが、ここでは素直にcopyを使うことにする。

オブジェクトのコピーやNSCopyingについては、Appleの『Memory Management Programming Guide for Cocoa』の"Implementing ObjectCopy"に詳しい解説がある。

2008-05-06

共同通信社記者『ハンドブック第11版』

以前かな漢字変換のATOKのオプションとしてこのハンドブックを辞書化した『記者ハンドブック辞書』を使用していて大変便利だった。合わせてこの共同通信社の『記者ハンドブック』を手元においておくと、非常に参考になる。

記者ハンドブック第11版
(社)共同通信社
共同通信社
売り上げランキング: 1741

かな漢字変換を使用していると、つい漢字を多く使いがち。例えば「比喩」とか「便箋」とか気がつくと書いている。このハンドブックを引けば「比喩→例え」や「便箋→便せん」などより平易な表現や書き方を示してくれる。このハンドブックで気づいて自分でも気をつけているのは以前は「私」と漢字をつかっていたが、本書によると一般的には「わたし」とひらがな書きした方がよいというのでそのように気をつけている。かな漢字変換に頼っていると、なかなか気づかない。

このハンドブックは記者が記事を書く時に使用される「新聞用字用語集」をベースに共同通信社でさらに練られたものだ。本書は3~4年ごとに改訂されているし、「新聞用字用語集」は今回10年ぶりに改訂されこの11版ではそれが反映されている。つまり、これを参考にすれば、ある程度トレンドを押さえ一般的にわかりやすく正しいとされる用字がわかる仕組みになっているということ。

また用字だけでなく、句読点などの解説や記事フォームなんてものもあり読み物としても大変面白い。個人的には「紛らわしい地名」の中で大学時代4年間毎日通学に利用してた大阪の阿野区にあるのJR天王寺駅の下にある地下鉄の駅名は「阿野橋」だが、隣接する近鉄の駅が「大阪阿野橋」だったということを発見した。

最近はブログで文章を書いている人も多いでしょうが、こういった一般的な指針を参考にしながら自身の流儀を作っていけば文章のレベルも上がるはず(?)

潮干狩り?

Digging Clams at the beach

連休の最終日になってやっと晴れたので、久しぶりに近所の千葉ポートタワーに行ってきた。丁度、着いたときには引き潮で皆潮干狩りを楽しんでいたので、息子と一緒に貝を掘り出したりカニを捕ったりしながら遊んだ。こんな東京湾も奥まったところに自然にあさりやカニがいるのだから驚く。とても食べようと言う気持ちにはならないけれど。

午後2時にはまた潮が満ちてきたのであっという間に、掘り返していた辺りも海水に沈んでいく。ポートタワーでここに来たときには恒例になっている千葉県産の牛乳で作ったソフトクリームを。甘さ控えめであっさり風味、けれどミルク特有の濃厚さも残したソフトクリームは最高にうまい。

なんとものんびり過ごせた午後だった。


www.flickr.com

2008-05-04

月島〜日本科学未来館

月島

日本科学未来館のエイリアン展にいくことになり、お昼に月島でもんじゃでも食べていこうかということなった。先日飲みにいった『』というお店がとても美味しかったからだ。

驚いたことに昼の月島ってのはものすごい人手なんだということ。もしかするとゴールデンウィークのためかもしれないが、有名店かどうかは関係なくどの店にも行列ができていてすぐに入れそうな店は洋食屋さんくらい。

結局目についた店で大きくて人の回転が早そうなバンビ2号店に並んだ。40分くらいでやっと店内に入った。注文は明太子チーズ餅もんじゃ、ビビンバもんじゃ、特製塩焼きそば。どれもハズシようのない品だが、個人的にはちょっと味が濃い目でった。味はそれなりだったけれど、忙しいせいかスタッフの対応はあまりよくなかった。

Alien

そのまま豊洲まで戻ってゆりかもめでテレコムセンターまでいって日本科学未来館に。しかしここでも館内への入場で30分以上、エイリアン展の入場でまた30分以上と行列に並ぶことに。

エイリアン展は4つのブースに分かれていたが最初の部分は映画などで出てきたエイリアンやよく「解剖された宇宙人」として紹介されるエイリアンの模型などばかり。「なんでこんなの科学未来館で?」って思っていたら、後半はちゃんと科学していた。想定された太陽系外の惑星環境での生物の趣味レーションなどはなかなか見ていても楽しい。

結局、今日一日、行列尽くしの日だった。

2008-05-03

Wireless Mighty Mouse

080502-151031.jpg

ExpertMouseが逝ってしまってから、しばらくiMacに付属していた尾っぽ付きのMighty Mouseを使用していた。小さなスクロールボールの使い勝手はなかなかだが、感圧サイドボタンの感度が敏感すぎてマウスを動かそうと持つたびにExposeが立ち上がったりしてどうもしっくりこない。

仕事用のPCで使用しているロジクールのVX-Rの使い心地がよいので候補に考えていたが、また専用ドライバーを入れなければならないとか、せっかくのBluetoothを使わずに専用のレシーバーをUSBに挿すというのもなんだかなぁとか悩んだあげくに、やはりWireless Mighty Mouseを購入した。

VX-Rは単三電池1本で稼働するが、Wireless Mighty Mouseのほうは単三2本でずっしりと重い。ただ、単三1本でも稼働できるようだ。この重さは私自身は気にならないので2本しっかりと入れる。リチウム電池が付属しているが、こちらは会社のVX-R用にして、エネループを2本入れた。


080502-151132.jpg

ロジクールと比較すると電池ケースなど少々作りが甘い気もするが、思ったよりはしっかりとしている。底面に電源スイッチがあるのだが、それがレーザーの部分にありシャッターも兼ねているという凝りよう(もっとも昔のおもちゃのスイッチのような機構で固くて爪を痛めそうだが)。

BlueToothでの接続だが、接続自体は簡単で「システム環境設定」から「Bluetooth」で使用をオンにして機器を追加するだけでサイドボタンやスクロールボールの機能までフルに使用できる。スリープからの復帰もマウスでできるので、尾っぽ付きのマウスと全く同様に使用できる。尾っぽがないだけ自由だ!

気になっていた感圧サイドボタンだが、尾っぽがないので持ち方がかわったせいか個体差であったのか、今回のMighty Mouseでは特にそういう問題もおこらない。ということでとっても気持ちよく使えている。こんなことであれば、早く購入しておけばよかった。

 

Apple Wireless Mighty Mouse MB111J/A
アップルコンピュータ (2007-08-09)
売り上げランキング: 762

Objective-Cの手習い:Singletonパターン

今回は『Java言語で学ぶデザインパターン入門』からSingltonパターン。

至って簡単なプログラムだが、Objective-Cでの注意点は3つ。

  1. クラス変数がないこと
  2. メソッドの可視性を設定できないこと
  3. 決まった形式でのコンストラクタのようなものがないこと

Javaなどではクラス変数にSingletonインスタンスを納めておくのが通常だが、Objective-Cではスタティック変数を用意して格納しておくことにする。@implementaion部の最初に以下のように宣言する。

static Singleton* s_singleton = nil;

また、2と3の問題からJavaのようにコンストラクタをプライベートにして生成を制御するということができない。

で、NSObjectから継承された新たにインスタンスを作成しそうな基本メソッドをまずオーバーライドしていく。具体的にはallocWithZone/copyWithZoneなどがそれにあたる。また解放に関する部分も勝手に解放されてはまずいので手を入れておく(retain/retainCount/release/autoreleaseなど)。

具体的にはSingletonクラスの基本メソッドのオーバーライド部分は以下のようになる。

+(id)allocWithZone:(NSZone*)zone
{
    @synchronized(self) {
        if(!s_singleton) {
            s_singleton = [super allocWithZone:zone];
        }
    }
    //アップルのガイドでは最初はインスタンスを返し以降はnilを返すことに
    //なっているが、それだとうまくいかないので以下のように常にインスタンス
    //を返すように変更
    return s_singleton; 
}

-(id)copyWithZone:(NSZone*)zone
{
    return self;
}

-(id)retain
{
    return self;
}
-(unsigned)retainCount;
{
    //解放できないオブジェクトであることを示す
    return UINT_MAX; 
}
-(void)release
{
    return;
}

-(id)autorelease
{
    return self;
}

で肝心のインスタンスを提供するメソッドは以下のようになる。

+(id)getInstance
{
    @synchronized(self) {
        if(!s_singleton) {
            s_singleton = [[self alloc] init];
            printf("インスタンスを生成しました。\n");
        }
    }
    return s_singleton;
}

@synchronizedを入れているのはマルチスレッドへの考慮だ。

実はこの辺りの解説はアップルが提供するデザインガイド「Cocoa Fundamentals Guide」に「シングルトンインスタンスの作成」という解説があり、コードのサンプルも掲載され詳しく説明されている。今回はほとんどその受け売り。

SingletonSample.zip

2008-05-01

六連星の申し子たち/第14回R1・R2

R2、そしてR1は、燃費や扱いやすさはもちろん、 こうしたカタチや色、質感や触感などの感性的な要素により、 性別を問わず幅広い層から支持をいただいています。

本当にそうだったらよかったのだが……

R1/R2の美点としてあげられた、デザイン、走り、安全性の3つは確かに軽自動車という枠ではすごい。

まず、デザイン。
「軽自動車でも枠一杯の大きさを確保しました」みたいな浅ましさがなく、コンパクトに見栄えよくまとまっているのがよい。三菱のi(アイ)と比較すると中途半端だとかいわれるが、評論家と言われる人たちが絶賛するデザインは伊達ではないと思う。残念ながらR2は整形してしまったけれど、あのスプレッドウィングのグリルデザインだってもう少しがんばっていれば受け入れられたかもしれない。

次にこの記事にもあるように走りのメカニズム。
4気筒エンジンと4輪独立サスペンションなどのメカへのこだわりは実際走りにも表れていた。あるサイトの燃費No.1はここ数年R2がずっと独走を続けているが、これはすごいことだと思う。

ただ、結局こういうことは既存のユーザーには受け入れられなかったのは事実。ハードはすごかったけれど、「軽自動車」を「安い小さな車」だけでないスタイリッシュでパーソナルな乗り物へという提案がきちんと売り手の末端まで浸透できていなかったように思う。

とかなんとかいいつつ、軽自動車からの撤退が決まった後この記事を書くのは辛かったろうなぁと思い

菊地美香公式ブログ: りにゅーある!!!

ついに念願叶い、ブログをリニューアルすることができました!!! コンセプトは「爽やかさ」

菊地美香さんの公式ブログがリニューアルされた。
といってもデザインがかわっただけだが、軽やかなデザインにかわっていた。

それはともかく記事中のWiiハンドルの写真を見て、「おっ!」 そうなんだ、ストラップは下へと垂らすんだ! わたしは上からぺろんと出してハンドルを握るときに手首に通していた。

なんてことを感心してしまった。

Objective-Cの手習い:TemplateMethodパターン

今回はTemplateMethodパターン。 『Java言語で学ぶデザインパターン入門』をベースにしているので、コードの意味などはこちらのJava版のソースコードを参照ください。

まずは素直にJavaのコードを移植したパターン(TemplateMethod1)。

Objective-Cには言語として抽象クラスのサポートがない。概念なのでプログラマーが勝手にやれよということらしい。で、サンプルコードではAbstractDisplayという名前になっているが実際にはサブクラスで実装を期待するメソッドについては空メソッドを定義している。

    -(void) open { }
    -(void) print{ }
    -(void) close{ }

呼び出す側のメイン関数も以下の通り

    char c = 'H';
    id d1 = [[CharDisplay alloc] initWithChar: c];
    id d2 = [[StringDisplay alloc] initWithString:@"Hello World!"];
    AbstractDisplay* d3 = 
               [[StringDisplay alloc] initWithString:@"日本語でこんにちは"];

    [d1 display];
    [d2 display];
    [d3 display];

結果は以下のようになる。

    <<HHHHH>>
    +------------+
    |Hello World!|
    |Hello World!|
    |Hello World!|
    |Hello World!|
    |Hello World!|
    +------------+

    +------------------+
    |日本語でこんにちは|
    |日本語でこんにちは|
    |日本語でこんにちは|
    |日本語でこんにちは|
    |日本語でこんにちは|
    +------------------+

これだけでは面白くないので、Objective-Cのクラスクラスタを使ってFactory的に実装してみる。(TemplateMethod2)

まず、AbstractDisplayの+(id)allocを以下のように定義する。

    +(id)alloc
    {
      self = [super alloc];
      if([self isMemberOfClass:[AbstractDisplay class]]) {
         PlaceHolderDisplay* disp = [PlaceHolderDisplay alloc];
         return disp;       
      } else {
         return self;
      }
    }

解説すると、最初に呼ばれたときには素直に親クラスのallocを呼び出し、自身がAbstractDisplayだったときはPlaceHolderDisplayをallocして返し、AbstractDisplayでなかったときはそのまま自身を返す。

PlaceHolderDisplayでは、以下のように2つの初期化メソッドだけが定義されている。

    -(id)initWithString:(NSString*) str
    {
      self = [[super init] autorelease];
      StringDisplay* disp = [[StringDisplay alloc] initWithString:str];
      return disp;
     }
     -(id)initWithChar:(char)ch
     {
       self = [[super init] autorelease];
       CharDisplay* disp = [[CharDisplay alloc] initWithChar:ch];
       return disp;
     }

ここでやっていることも、初期化で呼び出された際それぞれ見合った子クラスのインスタンスを生成して返す。

Javaな人から見るとalloc、つまりコンストラクタで自分とは別の子クラスのインスタンスを生成して返すなど邪道に思えるが、こうすることにより呼び出し側は以下のようになりこれらの子クラスのxxxxDisplayなどを意識することなくAbstractDisplayクラスのみを使う感覚で使用できることになる。

    id d1 = [[AbstractDisplay alloc] initWithChar:c];
    id d2 = [[AbstractDisplay alloc] initWithString:@"Hello World!"];
    AbstractDisplay* d3 = [[AbstractDisplay alloc] initWithString:@"日本語でこんにちは"];

実際、Cocoa/FoundationのNSStringクラスなどは抽象クラスで上記と同じような構成でデータ格納形式に応じて子クラスを生み分けているようだ。