从头开始编写Objective-C类

时间:2011-05-27 15:05:56

标签: objective-c

我想编写一个没有Cocoa或GNU Object.h的Objective-C类(用于教育目的)。我在网上挖掘,在我看来,很多人希望“随语言而来”的东西,例如类和消息发送,实际上是由第三方编写的文件中定义的,例如{{1} }。

是否有关于什么是真正纯Objective-C以及什么是运行时/框架的一部分的文档?我需要实现哪些功能才能在不使用任何第三方代码(如objc-runtime.hObject.h的情况下获得工作环境(请再次注意,这是出于教育目的,而不是用于生产代码)?< / p>

感谢您的任何见解!

4 个答案:

答案 0 :(得分:5)

真的,如果你不从NSObject继承,那么唯一必须照顾自己的是对象创建和破坏;无论其父类如何,否则方法的行为方式相同。 KVC和内存管理等功能是OpenStep / Cocoa的功能,但不是语言的一部分。

这是一个从头开始的课程:

@interface MyClass { // note the lack of a superclass here
    @private Class isa;
}
+ (MyClass *)create;
- (void)destroy;

- (int)randomNumber;
@end


@implementation MyClass
+ (MyClass *)create {
    return class_createInstance(self, 0);
}

- (void)destroy {
    object_dispose(self);
}

- (int)randomNumber {
    return rand();
}
@end

以下是它的使用方法:

int main(int argc, char **argv) {
    MyClass *foo = [MyClass create];
    if (foo) {
        printf("random! %i\n", [foo randomNumber]);
        [foo destroy];
    }
}

修改:如果您甚至不想使用class_createInstance()object_dispose(),则必须手动实现等效项,以及等效的{{} 1}}所以你知道一个对象占用了多少内存。但即使你管理它,也不要认为你已经逃脱了Objective-C运行时!消息调度仍然完全基于运行时中的C函数构建,并且Objective-C语法在编译期间转换为对这些函数的调用。

答案 1 :(得分:2)

Matt Gallagher写了一篇真正的cool post来编写一个简单的Cocoa程序。由于Objective-C是C的超集,你可以这样做:

echo "int main(){return 0;}" | gcc -x objective-c -; ./a.out ; echo $?

无论如何,你可能会因阅读他的帖子而得到很多。

答案 2 :(得分:1)

就避免框架和创建自己的基础对象而言,您需要做的就是确保第一个iVar被声明为Class is_a,并且您可能有一个合理的尝试来复制NSObject是通过通过运行时函数。

就避免运行时库和框架而言,这是不可能的。 Objective C(或者至少是不仅仅是C的位)是一种动态语言。因此,C不执行的所有操作都由运行时库处理。

有可能使用32位运行时和不推荐使用的API构建自己的类和对象,这不会抽象出类,协议等的布局到现代运行时的范围(我是只是真的用现代运行时来探讨)

也许你可以创建类,添加方法和分配实例,并通过在class_t结构中设置值然后使用malloc()进行分配,尽管如此,你仍然会在每次使用时隐式使用运行时函数objc_msgSend [obj selector]语法 - 除非你想要实现它,在这种情况下你只是自己重新实现了语言。您正在寻找语言的“纯核心”只是运行时。

答案 3 :(得分:1)

这是一个类的示例,不使用class_createInstance或object_dispose,或任何其他Objective-C运行时(至少我们不直接调用它们)。

#import <objc/objc.h>
#import <stdio.h>
#import <stdlib.h>
#import <string.h>

static Class __scratchClass = NULL;

@interface Scratch {
  Class isa;
  char *name;
}
+ (id) initialize;
+ (Scratch*) new:(const char*)strName;
- (void) sayHello;
- (void) destroy;
@end

@implementation Scratch

+ (id) initialize { 
  __scratchClass = self;
  return self;
}

+ (Scratch*) new:(const char*) strName {
  Scratch* pObj = (Scratch*)malloc(sizeof(Scratch));
  if (!pObj) return NULL;
  memset(pObj, 0, sizeof(Scratch));
  pObj->isa = __scratchClass;
  pObj->name = (char*)malloc(strlen(strName)+1);
  strcpy(pObj->name, strName);
  return pObj;
}

- (void) sayHello {
  printf("Hello, World!\nThis is Scratch (%s)...\n", name);
}

- (void) destroy {
  if (name) {
     free(name);
     name = NULL;
  }
  free(self);
}

@end

int main(int argc, char** argv) {
  Scratch* ps = [Scratch new:argv[0]];
  [ps sayHello];
  [ps destroy];
  return 0;
}

编译代码(假设您将其保存为'test1.m'):

gcc -o test1 test1.m -lobjc