HMDT - Logic and Intuition -

about HMDT

Cocoa Programming Tips 1001

Objective-C

クラス

Objective-C - クラス

Class とは

Keywords: Class

Objective-C で、オブジェクトのクラスを表すのは Class 型。で、結局のところ、この Class 型って何なの?

順に追っていこう。まず、Class 型の定義は /usr/include/objc/obj.c にある。

/usr/include/objc/objc.h

typedef struct objc_class *Class;

つまり、Class 型は、構造体 objc_class のポインタだ。構造体 objc_class の定義は /usr/include/objc/objc-class.h にある。

/usr/include/objc/objc-class.h

struct objc_class {
    struct objc_class *isa;	
    struct objc_class *super_class;	
    const char *name;		
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;

    struct objc_method_list **methodLists;

    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};

これが、メモリ上に展開される、クラスの実体になるわけだ。含まれている情報は、

  • isa
    このクラスの isa ポインタ
  • super_class
    親クラス
  • name
    クラスの名前
  • version
    バージョン
  • instance_size
    インスタンスの大きさ
  • ivars
    インスタンス変数のリスト
  • methodLists
    メソッドリスト(複数)
  • protocols
    プロトコル

っていう感じだ。これで、Objective-C の実行環境に必要な情報が、ほぼそろうね。

Objective-C - クラス

アプリケーションで使っているクラスをすべて取得する

Keywords: objc_getClassList

あるアプリケーションで、Objective-C runtime が持っているすべてのクラスを取得してみよう。そのための、そのものずばりの関数がある。objc_getClassList() だ。/usr/include/objc/objc-runtime.h に定義がある。

/usr/include/objc/objc-runtime.h

OBJC_EXPORT int objc_getClassList(
        Class *buffer, 
        int bufferLen);

この関数を呼ぶときは、buffer に Class のポインタが入るバッファを、bufferLen にはその大きさを指定するんだ。返り値は、クラスの数が入る。

ヘッダ objc-runtime.h に、この関数の使い方が書いてある。まず、buffer に NULL を指定して呼んでやる。そうすると、返り値として、クラスの数が返ってくるんだ。そうしたら、その大きさだけのメモリを確保して、もう一回呼んでやるんだ。クラスの数が多すぎたら、何回かに分けて呼んでやる。

showAllClasse() (sample)

#import <objc/objc-runtime.h>

void showAllClasses {
    int numClasses = objc_getClassList(NULL, 0);
    int i;
    Class* classes;
    Class* tmp;
    
    classes = malloc(sizeof(Class) * numClasses);
    objc_getClassList(classes, numClasses);
    
    tmp = classes;
    for(i = 0; i < numClasses; i++) {
        printf("%s?", (*tmp++)->name);
    }
    
    free(classes);
}

上のコードが、すべてのクラスにアクセスするサンプルだ。取り出した後に、そいつらの名前を printf() で表示させているよ。

Objective-C - クラス

クラスを階層表示する

Keywords: objc_getClassList

すべてのクラスを取得したので、それを階層表示させてみよう。Class 型、すなわち objc_class 構造体には、super_class という親クラスへのポインタがあるんだ。

/usr/include/objc/objc-class.h

struct objc_class {
    ...
    struct objc_class *super_class;	
    ...
};

これをたどっていけば、階層構造を知ることができる。ルートクラスは、これが nil になってるよ。

階層構造を表示する、簡単なアプリケーションを作ってみた。実際に階層を調べるところは、こんな感じになっている。

ClassViewerControll.m (sample)

    // Get all classes
    classes = malloc(sizeof(Class) * numClasses);
    objc_getClassList(classes, numClasses);
    
    tmp = classes;
    for(i = 0; i < numClasses; i++) {
        // Get class name
        classNameStr = [NSString stringWithCString:(*tmp)->name];
        [_classNameArray addObject:classNameStr];
        
        // Get super class name
        if((*tmp)->super_class != nil) {
            NSMutableArray*	array;
            
            superNameStr = [NSString 
                stringWithCString:(*tmp)->super_class->name];
            
            array = [_classNameHierDict objectForKey:superNameStr];
            if(array == nil) {
                // Create new array
                array = [NSMutableArray array];
                [_classNameHierDict setObject:array forKey:superNameStr];
            }
            
            [array addObject:classNameStr];
        }
        else {
            // This class should be root
            [_classNameRootArray addObject:classNameStr];
        }
        
        tmp++;
    }
    
    free(classes);

最初に、すべてのクラスを取得する。そして、それを一個ずつ走査していくんだ。まず、そのクラスの名前を調べる。次に、親がいるかどうかを、super_class を見ることによって、調べるんだ。親がいる場合は、その親の名前を key にして、dictionary につっこむ。いない場合は、これはルートクラスなので、それ専用の array に入れてるんだ。

class viewer

これで、root の array からたどっていけば、階層構造を知ることができるんだ。試しに作ってみたアプリケーションの実行結果は、右のような感じ。

■サンプルダウンロード:
ClassViewer.tar.gz

back to top content

Copyright © 2002-2006 HMDT. All rights reserved.