Objective-C有反射吗?

son*_*.vu 21 reflection objective-c

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

Yuj*_*uji 26

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

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

     if([foo isKindOfClass:[NSString class]]){ ... } 
Run Code Online (Sandbox Code Playgroud)

做方法名称所说的.您甚至可以动态添加方法.例如,

   #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;
  }
Run Code Online (Sandbox Code Playgroud)

这会产生输出

  Hi! from aeiou
  Hi! from bark
  Hi! from mew
Run Code Online (Sandbox Code Playgroud)

它的作用如下:

  1. SEL 是表示已发送消息(或方法调用,在其他术语中)的变量.
  2. resolveInstanceMethod:如果在类中未实现发送到实例的消息,则为Objective-C运行时调用类
  3. 因此,在这种情况下,我只是复制一个调用sayHi该方法实现的预定义方法的实现.
  4. 从该方法中,您可以使用_cmd查看调用该方法时使用的选择器.因此,即使从单个sayHi实现,我们也可以获得不同的输出.

一些标准的Cocoa实现(特别是Key-Value-Coding,Key-Value-Observing和Core Data)使用运行时动态修改类.


bbu*_*bum 14

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

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

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

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

在Objective C中,如何通过反射找出方法的返回类型?

Objective-C有标准库吗?

Objective-C上没有Smalltalk运行时功能?

当然,运行时也有很好的记录.就像语言一样.或者你可以阅读来源.


归档时间:

查看次数:

16658 次

最近记录:

9 年,6 月 前