我ながら馬鹿ではないのか? そのように思ってしまう

我ながら馬鹿ではないか、どうしてこんなプログラムにそれほど入れ込んでいるのか?

それでも大幅にブログラムが簡略化され、短くなっているのをどうしても記録しておきたいのです・・・

///////////////////////////
//  Cyclist.h
///////////////////////////
#import <Foundation/Foundation.h>

@interface Cyclist : NSObject
@property (copy) NSString* name;
@property (assign) float power;
-(id) init;
-(id) initWithName:(NSString*)name:(float)power;
-(NSString*) run:(float) slope;
-(NSString*) description;
@end

///////////////////////////
//  GrowingCyclist.h
///////////////////////////
#import "Cyclist.h"

@interface GrowingCyclist : Cyclist
-(NSString*)run:(float) slope;
@end

///////////////////////////
//  Utility.h
///////////////////////////
#import <Foundation/Foundation.h>

void MyPrint(NSString*);

///////////////////////////
//  Cyclist.m
///////////////////////////
#import "Cyclist.h"

@implementation Cyclist
@synthesize name;
@synthesize power;
-(id) init{
    if(self = [super init]){
    }
    return self;
}
-(id) initWithName:(NSString *)_name:(float)_power{
    if(self = [super init]){
        name = _name;
        power = _power;
    }
    return self;
}
-(NSString*) run:(float)slope{
    NSString* _temp;
    if(power >= slope) {
        _temp=[[NSString alloc]initWithFormat:@"%@ 登攀力 %.1fは、登れます!!", name, power];
    } else {
        _temp=[[NSString alloc]initWithFormat:@"%@ 登攀力 %.1fは、登れません", name, power];
    }
    return _temp;
}
-(NSString*) description{
    NSString* _temp=[[NSString alloc]
                     initWithFormat:@"[名前:%@] [登攀力:%.1f]", name, power];
    return _temp;
}
@end

///////////////////////////
//  GrowingCyclist.m
///////////////////////////
#import "GrowingCyclist.h"

@implementation GrowingCyclist:Cyclist
-(NSString*)run:(float)slope{
    NSString* _temp = [super run:slope];
    self.power += 0.5;
    return _temp;
}
@end

///////////////////////////
//  Utility.m
///////////////////////////

#import "Utility.h"

void MyPrint(NSString* str){
    printf("%s\n", [str UTF8String]);
    return;
}

///////////////////////////
//  main.m
///////////////////////////

#import <Foundation/Foundation.h>
#import "Cyclist.h"
#import "GrowingCyclist.h"
#import "Utility.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Cyclist* cyclist1=[[Cyclist alloc] initWithName:@"老成した齋藤":4.0];
        GrowingCyclist* cyclist2=[[GrowingCyclist alloc] initWithName:@"成長する齋藤":4.0];
        float slope = 3.0; int trial = 3;
        printf("****今度の坂道は%.1f度です これから%i回練習します****\n", slope, trial);

        MyPrint([cyclist1 description]);
        MyPrint([cyclist2 description]);
        for (int i=0; i<trial; i++){
            printf("@試技%i回目\n", i+1);
            MyPrint([cyclist1 run:slope]);
            MyPrint([cyclist2 run:slope]);
        }

        MyPrint([cyclist1 description]);
        MyPrint([cyclist2 description]);

        slope = 7.0; trial = 5;
        printf("\n\n****今度の坂道は%.1f 度です これから%i回練習します****\n", slope, trial);
        MyPrint([cyclist1 description]);
        MyPrint([cyclist2 description]);
        for (int i=0; i<trial; i++){
            printf("@試技%i回目\n", i+1);
            MyPrint([cyclist1 run:slope]);
            MyPrint([cyclist2 run:slope]);
        }
    }
    return 0;
}

これで結果出力は以下の通り

****今度の坂道は3.0度です これから3回練習します****
[名前:老成した齋藤] [登攀力:4.0]
[名前:成長する齋藤] [登攀力:4.0]
@試技1回目
老成した齋藤 登攀力 4.0は、登れます!!
成長する齋藤 登攀力 4.0は、登れます!!
@試技2回目
老成した齋藤 登攀力 4.0は、登れます!!
成長する齋藤 登攀力 4.5は、登れます!!
@試技3回目
老成した齋藤 登攀力 4.0は、登れます!!
成長する齋藤 登攀力 5.0は、登れます!!
[名前:老成した齋藤] [登攀力:4.0]
[名前:成長する齋藤] [登攀力:5.5]


****今度の坂道は7.0 度です これから5回練習します****
[名前:老成した齋藤] [登攀力:4.0]
[名前:成長する齋藤] [登攀力:5.5]
@試技1回目
老成した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 5.5は、登れません
@試技2回目
老成した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 6.0は、登れません
@試技3回目
老成した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 6.5は、登れません
@試技4回目
老成した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 7.0は、登れます!!
@試技5回目
老成した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 7.5は、登れます!!

自転車乗りプログラム改良

//
//  GrowingCyclist.m
//

#import "GrowingCyclist.h"

@implementation GrowingCyclist:Cyclist

-(NSString*)run:(float)slope{
    NSString* _temp = [super run:slope];
    self.power += 0.5;
    return _temp;
}

-(NSString*) description{
    NSString* _temp=[[NSString alloc]
                     initWithFormat:@"%@, 力はgrowingで初期値%.1f", [self name], self.power];
    return _temp;
}

@end

先ほどのプログラムでは class GrowingCyclistが折角 class Cyclistを継承しているのに、坂を登るか否かの判定methodがダブリ冗長でしたので、改良しました

自転車乗りプログラム Objective-C版

ようやく完成です 標準コンソール出力の NSLog()を使用すると、時刻とか色々な情報があわせて出力されるので、 Utility.hにおいて printf()を用いて結果のみ出力できるようにしました

///////////////////////////////////
//  Cyclist.h
///////////////////////////////////
#import <Foundation/Foundation.h>

@interface Cyclist : NSObject

@property (copy) NSString* name;
@property (assign) float power;

-(id) init;
-(id) initWithName:(NSString*)name:(float)power;
-(NSString*) run:(float) slope;
-(NSString*) description;

@end


///////////////////////////////////
//  GrowingCyclist.h
///////////////////////////////////
#import "Cyclist.h"

@interface GrowingCyclist : Cyclist

-(NSString*) run:(float) slope;
-(NSString*) description;

@end


///////////////////////////////////
//  Utility.h
///////////////////////////////////
#import <Foundation/Foundation.h>

int MyPrint(NSString*);


///////////////////////////////////
//  Cyclist.m
///////////////////////////////////
#import "Cyclist.h"

@implementation Cyclist
@synthesize name;
@synthesize power;

-(id) init{
    if(self = [super init]){
    }
    return self;
}

-(id) initWithName:(NSString *)_name:(float)_power{
    if(self = [super init]){
        name = _name;
        power = _power;
    }
    return self;
}

-(NSString*) run:(float) slope;{
    NSString* _temp;
    if(power >= slope) {
        _temp=[[NSString alloc]initWithFormat:@"%@ 登攀力 %.1fは、登れます!!", name, power];
    } else {
        _temp=[[NSString alloc]initWithFormat:@"%@ 登攀力 %.1fは、登れません", name, power];
    }
    return _temp;
}

-(NSString*) description{
    NSString* _temp=[[NSString alloc]
                     initWithFormat:@"%@, 力は%f", name, power];
    return _temp;
}

@end


///////////////////////////////////
//  GrowingCyclist.m
///////////////////////////////////
#import "GrowingCyclist.h"

@implementation GrowingCyclist:Cyclist

-(NSString*) run:(float)slope{
    NSString* _temp;
    if(self.power >= slope) {
        _temp=[[NSString alloc]initWithFormat:@"%@ 登攀力 %.1fは、登れます!!", self.name, self.power];
        self.power += 0.5;
    } else {
        _temp=[[NSString alloc]initWithFormat:@"%@ 登攀力 %.1fは、登れません", self.name, self.power];
        self.power += 0.5;
    }
    return _temp;
}

-(NSString*) description{
    NSString* _temp=[[NSString alloc]
                     initWithFormat:@"%@, 力はgowingで初期値%f", [self name], self.power];
    return _temp;
}

@end


///////////////////////////////////
//  Utility.m
///////////////////////////////////
#import "Utility.h"

int MyPrint(NSString* str){
    printf("%s\n", [str UTF8String]);
    return 0;
}


///////////////////////////////////
//  main.m
///////////////////////////////////
#import <Foundation/Foundation.h>
#import "Cyclist.h"
#import "GrowingCyclist.h"
#import "Utility.h"


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Cyclist* cyclist1=[[Cyclist alloc] initWithName:@"成熟した齋藤":4];
        GrowingCyclist* cyclist2=[[GrowingCyclist alloc] initWithName:@"成長する齋藤":4];
        float slope = 3.0;
        int n = 3;
        printf("****今度の坂道は%.1f度です これから%i回練習します****\n", slope, n);

        MyPrint([[NSString alloc]initWithFormat:@"%@は、練習開始前の登攀力が%.1fです", cyclist1.name, cyclist1.power]);
        MyPrint([[NSString alloc]initWithFormat:@"%@は、練習開始前の登攀力が%.1fです", cyclist2.name, cyclist2.power]);
        for (int i=0; i<n; i++){
            MyPrint([[NSString alloc]initWithFormat:@"%@",[cyclist1 run:slope]]);
            MyPrint([[NSString alloc]initWithFormat:@"%@",[cyclist2 run:slope]]);
        }
        
        slope = 7.0;
        n = 5;
        printf("\n\n****今度の坂道は%.1f 度です これから%i回練習します****\n", slope, n); 
        MyPrint([[NSString alloc]initWithFormat:@"%@は、練習開始前の登攀力が%.1fです", cyclist1.name, cyclist1.power]);
        MyPrint([[NSString alloc]initWithFormat:@"%@は、練習開始前の登攀力が%.1fです", cyclist2.name, cyclist2.power]);
        for (int i=0; i<n; i++){
            MyPrint([[NSString alloc]initWithFormat:@"%@",[cyclist1 run:slope]]);
            MyPrint([[NSString alloc]initWithFormat:@"%@",[cyclist2 run:slope]]);
        }
    }
    return 0;
}

これで結果出力は以下の通り

****今度の坂道は3.0度です これから3回練習します****
成熟した齋藤は、練習開始前の登攀力が4.0です
成長する齋藤は、練習開始前の登攀力が4.0です
成熟した齋藤 登攀力 4.0は、登れます!!
成長する齋藤 登攀力 4.0は、登れます!!
成熟した齋藤 登攀力 4.0は、登れます!!
成長する齋藤 登攀力 4.5は、登れます!!
成熟した齋藤 登攀力 4.0は、登れます!!
成長する齋藤 登攀力 5.0は、登れます!!


****今度の坂道は7.0 度です これから5回練習します****
成熟した齋藤は、練習開始前の登攀力が4.0です
成長する齋藤は、練習開始前の登攀力が5.5です
成熟した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 5.5は、登れません
成熟した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 6.0は、登れません
成熟した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 6.5は、登れません
成熟した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 7.0は、登れます!!
成熟した齋藤 登攀力 4.0は、登れません
成長する齋藤 登攀力 7.5は、登れます!!

ようやく少しずつ Objective-Cが分かってきました

新しい言語を使えるようになるのは これまでと全く違う世界が目の前に広がり、とても楽しくもかつ辛いものです。今回、年末よりObjective-Cという独特の世界観を持つ言語にとりかかりました。合計5冊の書籍を読みあさり、それと共に Internetで、各種の解説ページを読み、またPDFとして確保しました。

Objective-Cはいわずと知れた Mac OSXで使われている開発言語です。当初はとてもマイナーな言語でしたが、iiPhone/iPadの爆発的ブームと共に、主要言語の一つとなりつつあります。共に C言語をルーツに持つ Objective-Cと C++ですが、その両者はとんでもなく違うアプローチにより いわゆるオブジェクト指向言語を実現しました。まだこんなふうに評論的に述べられる立場ではないと思いますが、敢えて言わせてもらえば、C++は徹底的にコンパイラの道を歩み、その優位性は開発されたアプリケーションが有する圧倒的なスピードにあります。

一方 Objective-Cはどちらかと言えばインタプリタの道に近づき、その優位性は、実行時の圧倒的な柔軟性にありますが、スピートという点では C++には相当劣ります。

しかしながら、現在の hardware/CPUの進捗の前では 言語がもたらすスピードが重要な局面というのはものすごく限定されてきました。むしろ、いかにユーザーに応じて実行時に柔軟に変化できるか? そのようなアプリを用意に開発できるか? それが重要になってきたのです。それと共に、Objective-Cが脚光を浴びつつあるのです。

まあ、そんな御託を並べるよりも、要するに僕としては、MacBook Proの上で走るかっこいいアプリを、できるならば iPhoneで動く簡単なアプリを作れるようになりたいから、そして新しい世界を見て、そこに入れる自分がまだいるか、自分の脳味噌が未だ新しい物を受け入れるぐらいに柔軟であるか否か、それを検証するため、そんな目的で Objective-Cの勉強を始めたのです

最初は茨の道でした、だって もう端から概念が違うのです 「なになに メッセージ?」 そんなのmethodではないの? ここから始まります

ようやく、以前に C++で書いた自転車乗りを Objective-Cで書くことができました それは以下のようなものです

まずは宣言ファイルである、Cyclist.hとそれを継承する GrowingCyclist.hです

// Cyclist.h
#import 

@interface Cyclist : NSObject

@property (copy) NSString* name;
@property (assign) float power;

-(id) init;
-(id) initWithName:(NSString*)name:(float)power;
-(NSString*) run:(float) slope;
-(NSString*) description;

@end

そして GrowingCyclist.h

// GrowingCyclist.h
#import "Cyclist.h"


@interface GrowingCyclist : Cyclist

-(NSString*) description;

@end

そして、それぞれの定義ファイルである Cyclist.mをまずは

// Cyclist.m
#import "Cyclist.h"


@interface GrowingCyclist : Cyclist

-(NSString*) description;

@end

そして次は GrowingCyclist.mという定義ファイル

// GrowingCyclist.m
#import "GrowingCyclist.h"


@implementation GrowingCyclist:Cyclist

-(NSString*) description{
    NSString* _temp=[[NSString alloc]
                     initWithFormat:@"%@, 力はgowingで初期値%f", [self name], self.power];
    return _temp;
}

@end

そしてプログラム本体は以下のmain.mファイルです

// main.m

#import <Foundation/Foundation.h>
#import "Cyclist.h"
#import "GrowingCyclist.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        // insert code here...
        Cyclist* cyclist1=[[Cyclist alloc] initWithName:@"齋藤 滋":5.0];
        NSLog(@"名前は %@", cyclist1.name);
        NSLog(@"%@",[cyclist1 run:6.0]);

        GrowingCyclist* cyclist2=[[GrowingCyclist alloc] initWithName:@"growing齋藤 滋":10.0];
        NSLog(@"名前は %@", cyclist2.name);
        NSLog(@"%@", [cyclist2 run:6.0]);
        
    }
    return 0;
}

これで出力は以下の通り

2013-01-05 14:40:53.590 cycling[18188:303] 名前は 齋藤 滋
2013-01-05 14:40:53.593 cycling[18188:303] 齋藤 滋は登れません
2013-01-05 14:40:53.593 cycling[18188:303] 名前は growing齋藤 滋
2013-01-05 14:40:53.594 cycling[18188:303] growing齋藤 滋は登れます

もっとも今回はだんだんとslope角度を変化させたり、繰り返し練習させていませんので、最初登れなかったcyclistが次第に登れるようになることを simulateしてはいませんが、既に本質的な部分は理解できたのです。

非常に判りやすい説明ありがとう

ここに Mac OS-Xのメモリ管理方法についての判りやすい説明がありました 今勉強中なのです

Mac向けの開発言語として OS X v10.5 (Leopard) から Objective-C に代わって Objective-C 2.0 が導入されました.Objective-C 2.0 は Objective-C を大幅に拡張したものですが,その中の最大のものはガベージコレクタの導入でしょう.もはや retain/release は考えなくてよくなったのです.

その後登場した iOS (当時は iPhone OS)では Objective-C 2.0 が採用されましたがガベージコレクタは引き継がれませんでした.プログラマは手動で retain/release しなければならないのです.(リファレンスカウンタが使えるため C++ の new/delete よりははるかに安全ですが.)

OS X v10.8 (Mountain Lion) になり,この Objective-C 2.0 ガベージコレクタ機能は非推奨になりました.iOSとの整合性を考えると,iOSにガベージコレクタを搭載するか,OS X から再びガベージコレクタを取り除くかですが,アップルは後者を選択しました.(プログラマから見るとやや驚きですよね.)

そのかわり,Xcode 4.2 からコンパイル時に retain/release を自動的に挿入する機能が付きました.アップルはこの技術を Automatic Reference Count (ARC) と呼んでいます.

ガベージコレクタを前提にしたコードは変更の必要は(原則として)ありません.一方,Objective-C 1.0 時代のコードはおそらく NSAutoreleasePool を多用していると思いますが,この NSAutoreleasePool はサポートされなくなったため,書き直しが必要です.(おそらくいちばん簡単なコード移行方法は,retain/release を削除してしまうことです.)