objective-c 的一些东西

最近在看Objective-c
虽说是c语言扩展出来的…可是这里面的对象甚至类本身却是动态的…
查了下貌似这叫反射?
倒是和不少脚本型的语言很像…

了解下语法之类的可以看看这里(这篇东西同时有中文版),Wiki上还有些和C++的对比

一点点看下来,一开始还没什么,感觉只是语法变了下
嗯…#include变成#import

创建类用@interface,还可以继承,不过只能继承一个父类
objective-c的方法名很有特点…并不是完整名称后面跟参数列表…而是两者交织起来…
虽然这样打字可能要多些(没有带提示功能的编辑器的话,很吃力…),但是阅读起来更加明晰,不会出现忘记第几个参数是什么作用的情况了

实现类在@implementation块内写
这里就有些舒服了,方法名直接复制到对应的implementation块中就可以开始写方法的内容了
用C++的时候,要把成员函数的声明复制过来,然后在返回类型和函数名之间加上”类名::”的东西,感觉很麻烦呢…

this变成了self,要调用父类的方法而自身却重载过了这个方法时,可以对super调用方法
用-的是对象的method,用+的是类的method,后者相当于C++的静态成员函数

id类型是万能的对象,就像void*,对id对象可以调用任何方法,只要它的本体有这个方法就可以,没有的话…就会产生异常
看到后面感觉越来越玄乎…难道一个对象里存了一个方法列表,并且方法名和参数类型都有吗?…
事实上就是这样没错…一个对象指针所指的是个这样的结构体(摘自objc.h)

typedef struct objc_object {
  struct objc_class*  class_pointer;
} *id;

实际对象在这个基础上后面还会跟上它的成员变量…
而这个objc_class呢,则是这样的结构(摘自objc.h)

struct objc_class {
  MetaClass           class_pointer;          /* Pointer to the class's
                                                meta class. */
  struct objc_class*  super_class;            /* Pointer to the super
                                                class. NULL for class
                                                Object. */
  const char*         name;                   /* Name of the class. */
  long                version;                /* Unknown. */
  unsigned long       info;                   /* Bit mask.  See class masks
                                                defined above. */
  long                instance_size;          /* Size in bytes of the class.
                                                The sum of the class
						definition and all super
						class definitions. */
  struct objc_ivar_list* ivars;               /* Pointer to a structure that
                                                describes the instance
                                                variables in the class
                                                definition.  NULL indicates
                                                no instance variables.  Does
                                                not include super class
                                                variables. */
  struct objc_method_list*  methods;          /* Linked list of instance
                                                methods defined for the
                                                class. */
  struct sarray *    dtable;                  /* Pointer to instance
					         method dispatch table. */
  struct objc_class* subclass_list;           /* Subclasses */
  struct objc_class* sibling_class;

  struct objc_protocol_list *protocols;	      /* Protocols conformed to */
  void* gc_object_type;
};

其中值得注意的是objc_method_list,里面果然存在一个方法列表,只要在列表里查询匹配的方法就可以了,找不到还能在父类中找
再稍微深入一下,看看这个objc_method_list是什么东西(摘自objc-api.h)

typedef struct objc_method_list {
  struct objc_method_list*  method_next;    /* This variable is used to link
                                               a method list to another.  It
                                               is a singly linked list. */
  int            method_count;              /* Number of methods defined in
                                               this structure. */
  Method method_list[1];                    /* Variable length
                                               structure. */
} MethodList, *MethodList_t;

这是一个…链表…而且似乎是块状链表?
继续,找到Method的定义是(摘自objc-api.h)

typedef struct objc_method {
  SEL         method_name;                  /* This variable is the method's
                                               name.  It is a char*.
                                               The unique integer passed to
                                               objc_msg_send is a char* too.
                                               It is compared against
                                               method_name using strcmp. */
  const char* method_types;                 /* Description of the method's
                                               parameter list.  Useful for
                                               debuggers. */
  IMP         method_imp;                   /* Address of the method in the
                                               executable. */
} Method, *Method_t;

可以看到,一个方法包含一个SEL,一个参数表,一个IMP
SEL就是用@selector()可以得到的东西,上面虽然说包含方法名,但是我实际测试下来似乎不是这样…?版本不同吗?
IMP是真正可执行的函数的地址

于是像什么respondsToSelector:(判断一个对象有没有某个方法),performSelector:(执行某个方法),poseAsClass:(一个类完全由其某个子类扮演),这种神奇的函数也就不那么神秘了…

在objective-c中,类自身也是运行时存在的一个对象,想获取这个类的信息(比如类名)或修改这个类,应该是可以做到的
要新建一个类的实例,需要用类的alloc方法
也就是说,与其说是类,不如说是一个工厂对象…生产实例,以及记录这个实例所支持的方法列表之类的信息

做了个实验,建了个不继承其他类的类BObject,继承自BObject的类Rectangle
建了BObject,Rectangle,NSObject的实例,然后查看它们的指针以及meta类和父类的指针,画了下面的图
指针关系图
从方法列表的方法数来看,似乎左侧的只包含了”-”方法,其meta类包含了”+”方法
上面实验是在ubuntu下的GNUStep环境中做的…

稍微研究下机理,可以帮助了解很多本来不怎么好理解的特性,函数,用法,等

这里还有几篇较深入的文章

Tags: ,

2 条评论

rssComments RSS   transmitTrackBack Identifier URI

再加上垃圾回收就更像Java了 :P


评论 由 Answeror on 2010年08月14日 1:22 上午


垃圾回收啊…objective-c里面对象的引用计数都要手动来的…retain增加计数,release减少计数,计数器到0则释放,autorelease则由release pool释放的时候来对它们释放


评论 由 ben1222 on 2010年08月14日 2:13 上午


add留下评论