NSObject 类和 NSObject 协议
为什么可以重名?
在分析这两个的区别之前,我们先思考一个问题,为啥这两个长一样的东西不会发生命名冲突呢?
因为在 OC 中,类和协议是存在于不同命名空间的,所以一个作为类,一个作为协议,他们是可以重名的。
OC 中的基类
NSObject是基类,它再也没有超类。但是 OC 不像 Java 只有一个基类,OC 有多个基类,除了 NSObject 之外,还含有一个 NSProxy 基类和其他各种各样的基类。
NSObject 协议
拥有多个基类之后,也就引出了 NSObject 协议存在的理由,NSObject 协议规定了一些所有基类都需要实现的基本方法和属性,比如isEqual: 、isKindOfClass、respondsToSelector等,当然还有内存管理的方法 retain 、release、autorelease、retainCount等,这样就定义了一个相对统一的接口和 OC 对象都可以响应的方法。
我们可以看到这两个基类都遵从 NSObject 协议。
@interface NSProxy <NSObject>
@interface NSObject <NSObject>
NSProxy 基类
NSObject 基类除了遵从 NSObject 协议之外,还实现了一大堆别的方法,有时候,我们自定义的类并不需要这些方法。
比如我们自定义一些类,目的是进行一些消息转发,这个时候我们就可以让他继承自 NSProxy 基类,代表一些代理、转发作用的类,避免继承自 NSObject 引入大量不需要的方法。
我们可以看到 NSProxy 有这两个方法可以帮助实现消息转发:
- (void)forwardInvocation:(NSInvocation *)invocation;
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available");
现在让我们来尝试一下,首先定义一个类继承自 NSProxy,定义一个 object 属性,并且实现上面所说的两个方法:
@property (nonatomic,strong)NSObject *object;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
NSMethodSignature *methodSignature;
if (self.object) {
methodSignature = [self.object methodSignatureForSelector:sel];
}else{
methodSignature = [super methodSignatureForSelector:sel];
}
return methodSignature;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
if (self.object) {
[invocation setTarget:self.object];
[invocation invoke];
}
}
关于 NSInvocation 函数的调用可以参考小的之前写的这篇博文。
然后定义一个吃瓜群众类……将 Proxy 类收到的方法调用都传给他。
#import "Dog.h"
@implementation Dog
- (void)eat
{
NSLog(@"我是🐶,我想来点狗粮");
}
@end
实例化 Proxy 和 Dog,并且给 Proxy 传一个eat调用,可以看到,这个消息最终传给了 Dog:
ZNProxy *proxy = [ZNProxy alloc];
Dog *dog = [[Dog alloc] init];
//设置proxy的object为dog,以后proxy收到的消息最终都会传给dog
proxy.object = dog;
[proxy performSelector:@selector(eat)];
消息传给了Dog类