Objective-C有反射吗?

时间:2011-09-26 02:03:57

标签: objective-c reflection

我正在研究Objective-C,我想知道它是否具有反射的概念。到目前为止,我发现的所有文件都没有描述反思。

4 个答案:

答案 0 :(得分:25)

Runtime Reference中描述了运行时函数,它不仅允许查询类或实例的功能,还允许添加方法,甚至在运行时创建新类。我说这是一种非常动态的反射,通常不适用于基于C语言。 Mike Ash's wrappers是一个Objective-C包装器。再次,它甚至可以添加方法! Cocoa的基类NSObject也为许多运行时函数提供了包装器,请参阅NSObject protocol reference。例如

     [foo respondsToSelector:@selector(bar:)];

     if([foo isKindOfClass:[NSString class]]){ ... } 

执行方法名称所说的内容。您甚至可以动态添加方法。例如,

   #import <Foundation/Foundation.h>
   #import <objc/runtime.h>

   @interface Foo:NSObject
   {
   }
   @end
   @implementation Foo
   -(void)sayHi
   {
        NSLog(@"Hi! from %@",NSStringFromSelector(_cmd));
   }
   +(BOOL)resolveInstanceMethod:(SEL)sel
   {
        Method method=class_getInstanceMethod(self,@selector(sayHi));
        class_addMethod(self,sel,method_getImplementation(method),method_getTypeEncoding(method));
        return YES;
   }
   @end

   int main(){
    NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
        Foo* foo=[[Foo alloc] init];
        [foo aeiou];
        [foo bark];
        [foo mew];
        [pool drain];
        return 0;
  }

这会产生输出

  Hi! from aeiou
  Hi! from bark
  Hi! from mew

它的作用如下:

  1. SEL是表示已发送消息的变量(或方法调用,在其他术语中。)
  2. 如果发送到实例的消息未在类中实现,则目标C运行时调用类resolveInstanceMethod:
  3. 因此,在这种情况下,我只是将一个名为sayHi的预定义方法的实现复制到该方法的实现中。
  4. 从该方法中,您可以使用_cmd查看调用该方法时使用的选择器。因此,即使从单个sayHi实现,我们也可以获得不同的输出。
  5. 一些标准的Cocoa实现(特别是Key-Value-Coding,Key-Value-Observing和Core Data)使用运行时来动态修改类。

答案 1 :(得分:13)

是的,Objective-C有反射(和抽象类)。这种反思是否符合您的需求是一个不同的问题。

Objective-C中的反射对于C派生语言来说非常灵活。您可以向类询问它实现的方法,或者可以修改和/或向现有类添加方法。您甚至可以随时创建新类或随时更改任何实例的类。

一个典型的Objective-C程序不会做任何事情(至少不会直接)保存,偶尔会调用respondsToSelector:conformsToProtocol:。虽然Objective-C是一种完全动态的,反射的,面向对象的语言,但这并不意味着鼓励或通常使用这些模式。

您可能会发现我对这些问题的答案很有趣:

In Objective C, how to find out the return type of a method via reflection?

Does Objective-C have a Standard Library?

Smalltalk runtime features absent on Objective-C?

当然,运行时为very well documented。和the language一样。或者你可以read the source

答案 2 :(得分:1)

我想我不知道你在寻找什么方面的反思。您在寻找如何确定给定变量的类吗?如果是,请查看:Objective-C class -> string like: [NSArray className] -> @"NSArray"

// Get a object's class name
if ([NSStringFromClass([foo class]) compare:@"NSSomeObject"] == NSOrderedSame) {...}

// Does an object have a method
[foo respondsTo:@selector(method:)]

你还在寻找更多吗?

答案 3 :(得分:1)

有一群methods可以访问一个类的各种属性,并且可能是在一些对象内部“偷看”和“戳”。我从来没有和他们一起玩过,我所做的一点阅读表明他们远非完美,但他们似乎提供了一些“反思”的能力,类似于Java概念。