読者です 読者をやめる 読者になる 読者になる

C 言語で Objective-C っぽく OOP してみるテスト

C言語 Objective-C OOP

1 最初に

ただいま、C 言語で Objective-C っぽい Smalltalk なクラスのライブラリを作っています。
こんな感じに書きます:

#include <coreHezelnut/coreHezelnut.h>

int main()
{
    CHNTranscript_class_showCr( _S("Hello, World!") );

    return 0;
}

これは Objective-C の:

#import "Hezelnut/Hezelnut.h"

int main()
{
    [ HNTranscript showCr: @"Hello, World!" ];

    return 0;
}

と等価です。
CHNTranscript がクラスの名前、showCr がセレクタの名前です。
C 言語では関数の名前空間が 1 つしかないので、クラス名とセレクタ名をアンダーバーで繋ぐことで、 どのクラスのメソッドなのかを解りやすく表しているつもり…なんですが、流石にみっともないことになっていますね。
ここで使っている Transcript の showCr: は、Transcript のクラスメソッドなので、クラス名とセレクタ名の間には クラスメソッドであることを表す class を挟んでいます。

2 オブジェクトの作成

オブジェクトといっても、そこは C 言語ですから何らかの構造体へのポインタが返ってきます。
coreHezelnut では、オブジェクトの受け皿、つまり何らかの構造体へのポインタのエイリアスは ${クラス名}_ref で統一しています。
${クラス名} はそのクラスのクラス構造体へのポインタになっているので、注意してください。

struct ludor_cast {
    /// HP
    unsigned int hit_point;
    /// MP
    unsigned int masic_point;
    /// キャストの位置
    coord location;
    
};

この ludor_cast 構造体がオブジェクトの正体です。 ludor_cast 構造体へのポインタを仮に LDRCast オブジェクトと呼んでおきましょう。 LDRCast オブジェクトの型は LDRCast_ref で、オブジェクトを生成する関数が LDRCast_class_new です。

int main()
{
    LDRCast_ref cast = LDRCast_class_new();
}

こんな風に呼びます。