スキップしてメイン コンテンツに移動

Cocoa/Objective-Cの手習い

Objective-Cをちゃんと勉強して来なかったので、ここらでちゃんと勉強しようかと思いたった。まずは手習いとして、結城浩氏の『Java言語で学ぶデザインパターン入門』の各パターンでも移植してみよう。コード自体の意味や内容についてはそちらを参照してほしい。

第一回はIteratorパターン。 Objective-CではFoundationにIteratorを実装したNSEnumeratorが提供されているが、敢て実装してみる。

Objective-C自身は、オブジェクト指向の部分はC++などと違ってSmalltalkに近く、純粋に「らしい」コードを追求すればもっとよいコードがあるだろう。まず、JavaでいうInterfaceのようなものはないし、動的な指向が強く全てのオブジェクトがNSObjectというクラスに辿れるので本当はもう少し柔軟なコードが簡単に書けそうな気がする。が、ここは手習いなのでJavaのコードに準じたコードにしてみた。

まず、Javaのインターフェイスとして定義されているIteratorAggregateはObjective-Cでは少し異端とも思える静的な型付けを意識したProtocolを用いて以下のようなコードとする。

Iterator.h

    @protocol Iterator
    -(BOOL)hasNext;
    -(id)next;
    @end

Aggregate.h

    @protocol Aggregate
    -(id <Iterator>)iterator;
    @end

これら抽象クラスの実体としてBookShelfIteratorBookShelfを用意する。それぞれの宣言は以下の通り

BookShelfIterator.h

    @interface BookShelfIterator : NSObject <Iterator> {
        BookShelf* bookShelf;
            int index;
    }
    -(id)initWithBookShelf:(BookShelf*)shelf;
    @end

Aggregateの中での集合の扱いはNSMutableArrayを使用する。

BookShelf.h

@interface BookShelf : NSObject <Aggregate>
{
    NSMutableArray* books;
    int last;
}

-(Book*) getBookAtIndex:(int) index;
-(void) appendBook:(Book*)book;
-(int)getLength;
-(id <Iterator>) iterator;
@end

で、BookShelfIteratorIteratorとしてインターフェイス部分の実装は以下のような感じ

-(BOOL)hasNext
{
    if(index < [bookShelf getLength]) {
        return TRUE;
    } else {
        return FALSE;
    }
}

-(id)next
{
    Book* book = [bookShelf getBookAtIndex:index];
    index++;
    return book;
}
@end

Javaの例に即したテストコードは以下のようになる。 Book* book;

    book =  [[[Book alloc] initWithString:@"Around the World in 80 Days"] autorelease];
    [bookShelf appendBook: book];
    book =  [[[Book alloc] initWithString:@"Bible"] autorelease];
    [bookShelf appendBook: book];
    book =  [[[Book alloc] initWithString:@"Cinderella"] autorelease];
    [bookShelf appendBook: book];
    book =  [[[Book alloc] initWithString:@"Daddy-Long-Legs"] autorelease];
    [bookShelf appendBook: book];

   id <Iterator> it  = [bookShelf iterator];
   while([it hasNext]) {
        Book* book = [it next];
        NSLog(@"%@",[book getName]);
   }

   [bookShelf release];

恐らくProtocolを使う必要性は低いのだろうが……

デザインパターンの部分は余り考えることもなく終ったが、Javaのプログラマーが嵌りそうなところは、メモリー管理関連。いまではガベージコレクションもサポートされているが、デフォルトではプロジェクトの設定でオフになっている。自身でやるときは、自身でのretain/releaseautoreleaseを上手く意識して使うことが必要。

また、Cocoa/Foundationのクラスでは、[[Hogehoge alloc] init]で初期化すると普通にretain/releaseが必要だが、[Hogehoge hogehoge][Hogehoge hogehogeWithString]などのネーミングの初期化はautoreleaseが掛っている。なので、これらのオブジェクトはそのように扱わなければならない。また、GUIでなくコマンドラインのプログラムの場合、NSAutoreleasePoolが用意されない。Cocoa/Foundationのライブラリでは先の例のようにNSAutoreleasePoolを前提にしているものがあるので、自身で以下のように用意しなけばならない。

   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

     // プログラムの処理

  [pool drain];

最初これに気付かずに悩んでしまった。
もっとも、XCodeで新規プロジェクトを作成する際、「Command Line Utlity」 のなかから「Foundation Tool」を選んで作成すれば、このあたりのコードは 埋まったテンプレートを用意してくれるのだが。

次はAdapterかな。

増補改訂版Java言語で学ぶデザインパターン入門
結城 浩
ソフトバンククリエイティブ
売り上げランキング: 5728

コメント

このブログの人気の投稿

リピート

Appling 2ndの『リピート』 の記事を読んで、面白そうだったので買って読んでみた。 リピート posted with amazlet on 07.04.01 乾 くるみ 文藝春秋 (2004/10/23) 売り上げランキング: 194098 Amazon.co.jp で詳細を見る そもそもタイムスリップものは好きなジャンルであることと、そのタイトルと紹介されていたストーリーから大好きなケン・グリムウッドの『リプレイ』を連想したからだ。実際、作品の中でも時間を繰り返すタイムスリップを突きつけられた時主人公達はケン・グリムウッドの『リプレイ』を引き合いに出して議論を行う場面もあるので、作者がリプレイを意識しているのは確実だろう。 タイムスリップ物というSF的な文法を使いながら、うまくミステリーの要素を融合させ、ちょっぴり恋愛物のスパイスも利かせてうまい具合にまとまった作品になっている。たまたま今回は筋が読めてしまって「やっぱり」って感じもしたが、一般的には二つの要素がかみ合ってうまく最後まで読者を惹きつけるだろう。 帯には" 『リプレイ』+『そして誰もいなくなった』 "などと銘打ってある。確かに楽しめる作品であるが、ちょっと言いすぎかな。『リプレイ』のオマージュと考えると、以下の点で物足りなさを感じる。 リプレイ(リピート)の期間が短い 『リプレイ』では25年だったリプレイの期間がわずか10ヶ月を遡るだけ。このことで「人生を繰り返す」といっても重みが違ってきている。しかも描かれるのはそのあるサイクルだけだ。 描写される時代 『リプレイ』では自信を失っていた80年代のアメリカから良き時代の60年代、70年代がリプレイで描かれるところが大きな魅力になっている。一方『リピート』では振幅が短いためリピート自体にそういった効果はないが、何故かそもそもの設定は91年となっていて中途半端に懐かしい。 主人公が嫌なヤツ 最初は好青年っぽいがだんだん嫌な面が描かれていく。物語は一人称で綴られているが主人公がそんな状態であるため、読み手としては感情移入がし難い。 とはいえ、結構な長編だが一日で一気に読んでしまったほど面白い。

PaSoRi

Auの携帯 W41CAではFelica関連のアプリケーションをいくつか使っていたので、nineに移行するとこまるのではと思い、SonyのFelicaのリーダー/ライターであるPaSoRiを購入。 以前は「なんでこんなものお金払ってまで」と思ったものだが、実際にEdyを使うのに慣れてしまうと財布の出し入れなく買い物できたり、小銭をジャラジャラ持って歩かなくて済むメリットは大きい。オフィスにTallysが入っていて毎朝ここでコーヒーを買うのにもEdyを使っているので実感している。 携帯のEdyアプリだと残高やチャージがその場でできるが、カードだとお店に行かないとこういったことができないのはやはり不便だ。 SONY RC-S320 非接触ICカードリーダ/ライタ PaSoRi 「パソリ」 posted with amazlet on 07.05.20 ソニー 売り上げランキング: 15 Amazon.co.jp で詳細を見る Windows専用だがドライバとそれぞれのカードのアプリケーションが附属するので簡単に使用を開始できる。Edyのビューアーはバージョンアップしており最初の起動で最新バージョンを再導入するように促される。使用履歴や残額はその場で確認でいる。チャージはサービス登録をして手続きが完了するのに2日ほどかかるが、これもアプリケーションからオンラインで登録できる。カードは以前作ったANAのマイレージクラブのカードがあったので早速登録。 Macでは正式なサポートはない。 しかし、オープンソースで開発されている LibPaSori を利用したいくつかのアプリケーションがあり、例えば EdyValue データの読み出しだけならば可能となる。

隠された想い

あり得ない…… yostosには、『たまにでいいから相手して』という意味が込められています。 http://shindanmaker.com/69604 引用元: あなたのIDにはあなたの想いが隠されていたー