NSObject与<NSObject>协议

1,722 阅读2分钟

今天在研读objective-c编程之道的时候,看到了一段话

如果一个类既要是UIView的子类,同时又要是定制的抽象类型,那么这个抽象类型就只能是协议而不能是抽象基类。只对一个抽象类型进行子类化的类,可以让它们直接对抽象基类进行子类化。但是也许以后会改变设计,以使抽象类型也能够是UIView等的子类。能否两全其美?通常这种情况下灵活的做法是,首先为不需要子类化的其他类定义一个抽象基类,然后可以定义一个同名协议,让包括这个抽象基类在内的其他类去实现。在Cocoa Touch框架中你会发现类似的策略,例如,NSObject基类符合NSObject协议

刚开始的时候一直不太明白定义同名协议的原因是什么。特别是例子里面为什么NSObject 还要遵循一个的协议呢?

在面向对象编程中一条重要的法则是面向接口编程。意思是说一个对象要调用另一个对象的方法,不是采取直接调用的方式,而是通过调用某个实现了特定接口/协议或者继承了某个抽象类的对象这种方式来进行解耦。

其实NSObject和属于抽象基类和协议的关系。在iOS开发中,并不像java语言一样有abstract class和interface的存在,类似的存在是@protocol,它支持我们实现面向接口编程。

在Cocoa Touch中,并不是全部的类都继承自NSObject,如NSProxy。但是对于NSObject和NSProxy的派生类的对象的内存控制,仍然采用alloc、dealloc、retain、release和autoRelease是很自然的想法。在不改变NSProxy基类的情况下,就只能通过协议来支持。在NSObject协议中,声明了retain、release和autoRelease方法(alloc和dealloc在NSProxy有定义),而NSProxy实现了NSObject协议,因此可以做到[proxyObj release]这样的调用。

PS:NSObject协议的声明

@protocol NSObject

- (BOOL)isEqual:(id)object;
@property (readonly) NSUInteger hash;

@property (readonly) Class superclass;
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
- (instancetype)self;

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

- (BOOL)isProxy;//NSObject return NO;

- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

- (BOOL)respondsToSelector:(SEL)aSelector;

- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;

- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;

@property (readonly, copy) NSString *description;
@optional
@property (readonly, copy) NSString *debugDescription;

@end