Category(分类/类目):
利用Objective-C的动态运行时分配机制,Category提供了一种比继承更为简洁的方法来对class进行扩展,无需常见对象类的子类就能为现有的类添加新方法,可以为任何已经存在的class添加方法,包括哪些没有源代码的类。
注意:
- 无法向类中添加新的实例变量,类别没有位置容纳实例变量。(可用runtime方式实现添加实例变量);
- 当类别中的方法与原始类方法名称冲突时,类别具有更高的优先级,类别方法取代初始方法从而无法使用原始方法。(方法加载顺序:父类->子类->分类,后加载覆盖前加载)
Protocol(协议):
类似C++中的虚类,java中的接口,不负责实现,只负责声明。其他子类继承该虚类,需要实现申明的方法。(常用场景:代理)
特点:协议多用在许多类使用相同的方法而且这些代码重复性很大的情况下,把这些重复的代码提炼出来放在一个协议中,供大家使用。类似于java中的接口与C++中的纯虚函数的抽象类,它提供协议的规则,使用者只有遵从了协议的规则才能使用它提供的方法。当然这些方法只是在协议中申明了,并没有具体的实现。当使用者遵从这个协议并使用它的方法是,如果在类声明文件中方法都是默认的或者是@required时,那么在类实现文件中必须全部地实现这些方法,如果是@option标记的,使用者可以选择性实现。
过程:它只有.h声明文件,它既可以作为一个单独的文件进行声明所提供的方法,也可以直接放在类声明文件中进行声明,一般采用后者进行声明。它的方法声明时有默认、@required、@optional三种情况。当使用前面两种时,在类实现文件中必须全部地实现这些方法。如果是@optional标记的,使用者可以选择性的实现,视情况而定。当它的方法没有@optional时,那么它就类似于接口中的abstract整个类是抽象的,是必须全部实现所有的方法的。
格式:
@protocol TestProtocol <NSObject>
///默认必须实现
- (void)getCount;
@required
///设置required 必须实现
- (void)getNum;
@optional
///设置optional 可选实现
- (void)getTitle;
@property (nonatomic,assign) int number;
@end
Extension(扩展):
匿名的Category(特殊的)。类有时需要一些只为自己所见,所用的私有实例及私有方法可以通过扩展的方式声明,定义的方法在类本身的@implementation代码区域中实现。与Category不同的地方:可增加私有属性,声明的方法必须实现。作用:将方法变为类的私有方法。(只有.h文件,可以添加是咧变量和方法)
顺便提下继承:
继承:
- 特点: 继承多用于一般父类中的方法功能比较齐全,子类从父类继承过来使用,可以省略很多重复的代码,不仅简化了代码,而且也提高了代码的复用性。
- 过程: 当子类需要的方法和属性在父类中找不到时,子类可以添加自己必要的方法和属性,目的是对功能进行扩充;当父类中有子类需要的方法,但是方法中内容并不能完成子类的需要时,子类可以重新实现这个同名的函数,它会覆盖父类的同名函数来实现子类的需要的内容。
其他场景:
Protocol 可以声明属性,当声明的属性在某个类中使用时需要使用关键字@synthesize 同步生成get 、set方法,否则不可用,如下是某个类遵守TestProtocol时用到number属性:
@synthesize number = _number;
- (int)getNumber{
return 3;
}
- (void)setNumber:(int)number{
_number = number;
}
匿名扩展若直接卸载类文件implementtation中,使用实例时无需使用@synthesize,若单独建立文件需要使用@synthesize,如下
@interface UIViewController ()
@property (nonatomic,assign) int extensionCount;
@end
@interface ViewController ()<TestProtocol>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.extensionCount = 3;
NSLog(@"extension中的属性时:%d",self.extensionCount);
}
@synthesize extensionCount = _extensionCount;
类继承同理,如果父类声明属性未同步实现get 、set方法,需要在子类使用时用到@synthesize。(场景:父类对某个属性声明@dynamic,在需要使用的时候,由子类去实现,符合runtime机制,动态加载)若父母未做限制,目前xcode版本无需使用@synthesize。如下:
@interface BaseViewController : UIViewController
@property (nonatomic,strong) NSString *tip;
@end
#import "BaseViewController.h"
@interface BaseViewController ()
@end
@implementation BaseViewController
@dynamic tip;
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
@interface ViewController : BaseViewController
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tip = @"提示";
NSLog(@"提示是:%@",self.tip);
}
@synthesize tip = _tip;
- (void)setTip:(NSString *)tip{
_tip = tip;
}
- (NSString *)getTip{
return _tip;
}
@end