通过类别在运行时扩展对象?

时间:2015-10-31 18:18:37

标签: objective-c

  

与C ++等类似语言相比,Objective-C的对象非常灵活,可以在运行时通过类别或运行时函数进行扩展。

知道这句话是什么意思吗?我对Objective-C相对较新

2 个答案:

答案 0 :(得分:1)

虽然技术上是正确的,但读者可能会在运行时调用类别扩展名而感到困惑。正如Justin Meiners所解释的那样,类别允许您向现有类添加其他方法,而无需访问现有类的源代码。在Objective-C中使用类别是相当普遍的,尽管存在一些危险。如果两个不同的类别将相同的方法添加到同一个类,则行为未定义。由于您无法知道系统的其他部分(甚至是系统库)是否添加了类别方法,因此通常必须添加前缀以防止冲突(例如,而不是swappedString,更好的名称可能是某种东西例如rnc_swappedString,如果它是RNCryptor的一部分。)

正如我所说的那样,在运行时添加类别在技术上是正确的,但从程序员的角度来看,类别被编写为只是类的一部分,因此大多数人认为它们是编译时选择。在运行时决定是否添加类别方法是非常罕见的。

作为初学者,您应该了解类别,但创建新类别会很慢。创建类别是一种中级技能。这不是要避免的事情,而是你每天都会使用的东西。过度使用它们非常容易。有关更多信息,请参阅Justin的链接。

另一方面,“运行时函数”确实在运行时向现有类甚至特定对象添加新功能,并且完全受代码控制。您可以在运行时修改类,使其响应之前未响应的方法。您甚至可以在运行时生成全新的类,这些类在编译程序时不存在,您可以更改现有对象的类。 (这正是Key-Value Observation的实施方式。)

使用运行时修改类和对象是一项高级技能。在您拥有丰富的经验之前,您甚至不应该考虑在生产代码中使用这些技术。当你有这种经历时,它会告诉你,你很少这样做。您将了解运行时函数,因为它们是基于C的,名称为method_exchangeImplmentations。你不会将它们误认为是正常的ObjC(你通常必须导入objc/runtime.h才能找到它们。)

有一个中间地带流入运行时操作,称为消息转发和动态消息解析。这通常用于代理对象,并使用-forwardingTargetForSelector+resolveInstanceMethod和一些类似的方法实现。这些工具允许类在运行时修改自己,并且比修改其他类(即“混合”)要危险得多。

考虑如何将所有这些转化为Swift也很重要。一般来说,Swift不鼓励并限制运行时类操作的使用,但它包含(并改进)类别类扩展。当你有足够的经验深入挖掘运行时,你可能会发现它比现在更加模糊。但是你会在每个程序中使用扩展(Swift的类别版本)。

答案 1 :(得分:0)

类别允许您向无法访问(系统框架,第三方API等)源代码的现有类添加功能。通过在运行时向类添加方法,可以实现此功能。

例如,假设我想向NSString添加一个方法,用于交换名为-swappedString的大写和小写字母。在静态语言(例如C ++)中,像这样扩展类更加困难。我必须创建一个NSString(或辅助函数)的子类。虽然我自己的代码可以利用我的子类,但是在库中创建的任何实例都不会使用我的子类,也不会使用我的方法。

使用类别我可以扩展任何类,例如添加-swappedString方法并在类的任何实例上使用它,例如NSString透明[anyString swappedString];

您可以从Apple's Docs

了解更多详情