我第一次接触Java的时候就觉得整个反射包都很新颖,它使得Java和解释型的脚本语言更接近了,与此同时也拉开了和主流的C和C++的距离。在运行时可以窥视到一个对象的类元数据真的很不可思议,尽管这些可能不会在日常应用编程中经常使用到。从Java转到Objective-C的程序员应该会乐见Objective-C也支持反射。实际上,Objective-C有很多诸如动态改变类定义以及创建一个新类的动态特征。不过很难说这些功能有多大的作用,这也让我觉得Objective-C是一个有些臃肿的语言。在我看来,Objective-C有一个定位危机:它是解释型语言还是编译语言?运行时很大程度上是动态的。和C++不同,Objective-C是运行时绑定的。这也是为什么我们可以在实现时定义一个从来没有在头文件中声明的方法,或者通过Category扩展类。不幸的是由于这种臃肿使得找到一些日常编程中有用的东西变得困难,本文就是要去发现其中的一些“宝藏”。

根类NSObject

大部分(如果不是全部的话)的动态反射支持来自NSObject类。和Java的Object对象类似,NSObject是所有类(除了一些很少见的例外)的根类。所以所有你写的类应该都可以支持反射。需要指出的所有这些的反射支持并不是Objective-C语言的一部分,而是源于NS*的运行时环境。这也是为什么这些东西感觉被加入一些额外东东的原因。因为它就是被加入了额外东东。

获取类的元数据   通过调用如下的类方法你就可以获取到一个对象的类的元数据:

  1. Class c = [self class];

该方法既是实例方法也是类方法。它返回一个带有很多神奇信息的C构造体,比如实例变量、方法等等。所有这些和java.lang.reflect包相比都有些过时了,利用Objective-C访问这些信息的接口看起来很复杂。这可能就是故意设计成这样来“过滤”一些不合格的程序员。目前为止我唯一使用这些的地方就是为下面将要介绍的isKindOfClass:方法提供参数。一直以来我都不需要去窥视类结构的内容。

动态方程调用   我已经在方法调用一文中介绍了反射的一个方面。这使得你可以在运行时创建一个方法调用并传入参数。这和Java中使用java.lang.reflect.Method类很相似。

检查继承关系

Java有一个名为instanceof的操作符可以用来检查一个对象是否是一个特定类或者接口的实例。Objective-C也有类似的功能,就是通过isKindOfClass:方法。isKindOfClass:会在消息接收者是指定类及其子类的实例的情况下返回YES。比如有一个关联的指针数组,这样就可以根据其类型进行不同的操作:

  1. for(BaseClass* base in myArray) {
  2. if([base isKindOfClass:[ClassOne class]]) {
  3. // do stuff specific to ClassOne
  4. }
  5. else if([base isKindOfClass:[ClassTwo class]]) {
  6. // do stuff specific to ClassTwo
  7. }
  8. else if([base isKindOfClass:[ClassThree class]]) {
  9. // do stuff specific to ClassThree
  10. }
  11. }

如果你需要一个精确的类匹配,而不是匹配任何继承类,你就可以使用isMemberOfClass:方法。

检查是否符合协议   和实例检查类似,你可以测试一个对象是否符合特定的协议。Java在类和接口的情况下都使用instanceof方法搞定,但Objective-C使用了一个更笨重的方法。在测试是否合规的时候,应该使用conformsToProtocol:方法:

  1. BOOL conforms = [obj conformsToProtocol:@protocol(MyInterface)];

检查方法是否存在   对于像我这样Java和C++的老手来说,如果不知道一个对象是否实现了一个方法就很奇怪了。但是Objective-C的类很大程度上是动态的,你就需要检查你需要的方法是否存在。这就需要respondsToSelector:方法。如下代码就是检查接收者是否实现(或者继承)了指定方法:

  1. if([obj respondsToSelector:@selector(aMethod:)]) { // it's there, so we can call it [obj aMethod:YES]; }

当然,利用Objective-C的反射你可以做更多的事情,这里我只是尝试谈谈反射机制最常见的应用。如果你需要在你的软件中加入核心的动态特性,你就需要熟悉下这些文档:Runtime Programming Guide:Introduction Runtime Reference

Objective-C的反射的更多相关文章

  1. Automake

    Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...

  2. 【IOS 开发】Objective - C 面向对象高级特性 - 包装类 | 类处理 | 类别 | 扩展 | 协议 | 委托 | 异常处理 | 反射

    一. Objective-C 对象简单处理 1. 包装类 (1) 包装类简介 NSValue 和 NSNumber : -- 通用包装类 NSValue : NSValue 包装单个 short, i ...

  3. objective c实现配置文件+反射

    1. 先写plist配置文件 plist写到resouce里面去 通过NSBundle把数据取plist读出来 2. 通过NSClassFromString创建类 NSClassFromString ...

  4. 隐私泄露杀手锏 —— Flash 权限反射

    [简版:http://weibo.com/p/1001603881940380956046] 前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱.社交网站 ...

  5. Java学习之反射机制及应用场景

    前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...

  6. 关于 CSS 反射倒影的研究思考

    原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...

  7. 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)

    建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...

  8. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  9. .NET面试题系列[6] - 反射

    反射 - 定义,实例与优化 在面试中,通常会考察反射的定义(操作元数据),可以用反射做什么(获得程序集及其各个部件),反射有什么使用场景(ORM,序列化,反序列化,值类型比较等).如果答得好,还可能会 ...

  10. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

随机推荐

  1. 【转】关于onActivityResult方法不执行的问题汇总

    首先说说本人碰到的于onActivityResult不执行的情况.(网上找了很久都没有人碰到) 1.直接上代码说明 ActivityA的代码:(放在onCreate方法中) Intent intent ...

  2. java 加减乘除错误

    有次做一个for循环(1000次左右),做的事情也是很简单的事情,就是   Double testValue = (long类型 / 8 ) * long类型 的一些加减乘除操作, 但是总是出现一些数 ...

  3. div垂直居中的方法(转)

    在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...

  4. Effective C++ 笔记三 资源管理

    条款13:以对象管理资源 许多资源被动态分配于heap内而后被用于单一区块或函数内.它们应该在控制流离开那个区块或函数时被释放.标准程序库提供的auto_ptr正是针对这种形式而设计的特制产品.aut ...

  5. Oracle 特殊字符模糊查询的方法

    最近在写DAO层的时候,遇到一个问题,就是使用like进行模糊查询时,输入下划线,无法精确查到数据,而是返回所有的数据. 这让我很好奇,百度之后才发现,原来是因为有些特殊字符需要进行转义才可以进行查询 ...

  6. WCF学习笔记一(概述)

    WCF  Windows Communication Foundation 分布式通信框架.WCF是对现有分布式通信技术的整合.是各种分布式计算的集大成者.主要整合技术如下图: WCF的服务不能孤立的 ...

  7. Android - Unable to execute dex: Multiple dex files define

    这种提示的意思是说,引用的文件重复了.在引用json解析库中,clean工程的时候,报错说: Unable to execute dex: Multiple dex files define Lorg ...

  8. A题笔记(10)

    No.1390 代码:https://code.csdn.net/snippets/191965  另一版本:https://code.csdn.net/snippets/192009 考察点有两个: ...

  9. SQL使用数据库引擎存储过程,系统视图查询,DBA,BI开发人员必备基础知识

    在开发过程中会遇到需要弄清楚这个数据库什么时候建的,这个数据库中有多少表,这个存储过程长的什么样子等等信息,今天把自己工作过程中经常用到的一些数据库引擎存储过程,系统视图等等总结一下以备不时之用.下面 ...

  10. OC基础-day04

    #pragma mark -  Day04_01_匿名对象 1. 如果函数有返回值 我们可以不使用变量接收返回值. 而是直接将函数写在要使用其返回值的地方. 2. 正常情况下.我创建对象. 是使用了1 ...