二:Objective-C类与继承和协议
在前面已经提过了对象的初始化,这里首先讲的是变量。
2.1 变量
- 局部变量(内部变量): 局部变量是在方法内作定义说明的,其作用域仅限于方法内,离开方法后使用这种变量是非法的。
-
全局变量(外部变量): 其作用域是整个源程序。说明符是extern。例如:
extern int intX;
如果同一源文件中全局变量与局部变量同名,则在局部变量作用域内,全局变量不起作用。
3. 实例变量:在类中定义的实例变量,可以在各个方法内使用。
4. 静态变量(static):它是方法内部定义的类似于全局变量,作用域为当前类的所有对象。节省内存,静态变量之存储一处,供所有对象共用,可更新,更新后,所有对象访问更新后的值。
5. auto:这是声明一个自动局部变量,是方法内部变量的声明方式,是默认设置,一般省略它。
例如:auto int intX 与 int intX 等效。
6. const: 不可改变的变量。
7. volatile:与const相反,该变量的值会发生改变。
2.2 @property 与 @synthesize
在接口文件(.h)中,用@property来标识属性(实例变量);在实现文件(.m)中,用@synthesize来标识所声明的属性,让系统自动生成设置方法与获取方法(getter/setter)。
声明property的语法为: @property (参数1,参数2) 类型 名字;
其中参数主要分为三类: 读写属性: (readwrite/readonly) setter语意:(assign/retain/copy) 原子性: (atomicity/nonatomic)
各参数意义如下:
readwrite:产生settergetter方法。
readonly:只产生简单的getter,没有setter。
assign:默认类型,setter方法直接赋值,而不进行retain操作。
retain:setter方法对参数进行release旧值,再retain新值。
copy:setter方法进行Copy操作,与retain一样。
nonatomic:非原子性访问。如果没有这个关键字,会把self作为一个mutex,从而保证了原子性。
“.”操作只能够在setters和getters中。
例如:在接口文件中: @property int count;
等效于声明2个方法:
- (int)count; - (void)setCount:(int)newCount;
实现文件(.m)中: @synthesize count;
等效于在实现文件(.m)中实现2个方法--默认的assign:
- (int)count { return count; } -(void)setCount:(int)newCount { count = newCount; }
2.3异常处理
- @try:可能会抛出异常的代码块使用。
- @catch:用于捕捉@语块中抛出的错误,可以用多个@catch语句块。
- @finish:无论哪种情况都要执行的语句块。
- @throw:自己抛出一个错误。
2.4 基础框架类
- NSString:字符串类型,没有携带字体和大小的信息,不能改变NSString对象的字符串内容,但可以有很多方法可以由一个字符串产生另一个字符串。如果要改变这个字符串本身,需要用到NSString子类NSMutableString。
- NSDate:代表时间和日期。
- NSNumber:包含一个数值(包含bool)的对象。NSNumber本身不是一个数字,所以不能在算术表达式中使用。
- NSData:序列字节,不可修改。要修改的话需要用到NSData子类NSMutableData。NSData主要用于从网上下载数据(以NSData对象返回数据);把对象存储在文件中;读取文件数据(将NSData对象当做缓存区)。
- NSSet:无序的不同对象的集合,不可变,可通过调用方法增加或删除一个集合来获得新的NSSet对象。它的子类是NSMutableSet。
- NSDictionary:其键值对的无序集合,键通常是NSString,值可以是任何一个对象,NSDictionary是定长的,它的变长子类是NSMutableDictionary。
- 属性列表
- NSObject:每个类都是从NSObject继承来的,它采用NSObject协议,它实现了与NSCopying、NSMutableCopying和NSCoding 协议相关的方法,详细分析请看2.5.3的类别、2.5.4的协议部分与源码NSObject.h。
2.5继承与协议
2.5.1object-c继承基础
- object-c不支持多重继承,只能单继承,一个类只能有一个父类。
- 方法重写:若子类中的方法与父类的某一方法具有相同的方法名、返回类型和参数表,则新方法覆盖原有方法。
- 方法重载:类中可以创建多个方法,他们具有相同的方法名,但具有不同的参数和不同的定义,调用方法时通过传递给他们不同个数和类型的参数来觉定使用哪个方法。 方法名一定相同;方法的参数表必须不同,包括参数的个数和类型,以此区分不同的方法体; 方法的返回类型和修饰符可以相同也可以不同。
- self:一个类中的方法调用同一个类的另一个方法是使用self,代表本身,相当于this。
- super:表示父类,可以使用super访问父类中被子类隐藏或重写的方法。
2.5.2 访问控制
- @protected—Methods defined in the class and any subclasses can directly access the instance variables that follow.This is the default case. 该类和任何的子类中的方法可以直接访问这样的变量,这是默认的。
- @private —Methods defined in the class can directly access the instance variables that follow, but subclasses cannot. 该类中的方法可以访问这样的变量,但不能被子类定义的方法直接访问。
- @public —Methods defined in the class and any other classes or modules can di- rectly access the instance variables that follow. 除了自己和子类中的方法外,也可以被其他类或者其他模块中的方法所访问。开放性最大,但最好避免使用这个作用域。其他类应该使用getter/setter方法来访问或设置其他类上的实例变量,确保封装性。
2.5.3 类别
类别的作用:对已经存在的类的扩展,而又不影响原类的情况,Object-C提供了category动态运行时分配,为类添加新的方法。类的实现将分散到多个不同文件或多个不同框架中。
类别的特点:第一: category不像子类,不能定义新的实例变量。第二:名称冲突,即类别中的方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。例如:
@interface NSObject (NSCoderMethods) //表示类别的名称为NSCoderMethods,要扩展的对象为NSObject + (NSInteger)version; + (void)setVersion:(NSInteger)aVersion; - (Class)classForCoder; - (id)replacementObjectForCoder:(NSCoder *)aCoder; - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder; @end
类别标准的语法格式如下:
#import “类名.h” @interface 类名 (类别名)//新方法的声明 @end #import “类名类别名.h” @implementation 类名 (类别名) //新方法的实现 @end
2.5.4 协议
协议的功能类似于c++中对抽象基类的多重继承。协议是多个类共享方法的列表。协议中列出的方法在本类中并没有相应的实现,而是由别的类来实现这些方法。如果一个类要遵守一个协议,该类就必须实现特定协议的所有方法(可选方法除外)。
定义一个协议需要使用@protocol指令,紧跟着是协议名称,然后是声明的一些方法,在指令@end之前的所有方法的声明都是协议的一部分。
协议时可以有静态函数。
@optional表示可以不选择实现方法。
@required表示一定要实现的方法。
同时采用多个协议只需要在<>内列出多个协议,并用“.”隔开:
@interface Car :NSObject <NSCopying,NSCoding>。
下面的NSObject.h:每个类都是从NSObject继承来的,它采用NSObject协议,它实现了与NSCopying、NSMutableCopying和NSCoding 协议相关的方法。
/* NSObject.h */ #import <Foundation/NSObjCRuntime.h> #import <Foundation/NSZone.h> @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; @class Protocol; /*************** Basic protocols ***************/ @protocol NSObject //NSObject协议 //@protocol是声明协议的标志。后面的NSObject是协议的名称 //协议中的方法是每个采用者必须实现的方法,这里有19个方法 - (BOOL)isEqual:(id)object; // 用于对象比较 - (NSUInteger)hash; - (Class)superclass; - (Class)class; - (id)self; - (NSZone *)zone; - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; /* 延迟调用参数提供的方法,参数所需参数用withObject传入(类似于ActionScript3.0中的setTimeout函数) delay单位:秒 */ - (BOOL)isProxy; - (BOOL)isKindOfClass:(Class)aClass; /* 用于判断对象是不是参数提供的类型 */ - (BOOL)isMemberOfClass:(Class)aClass; /* 用于判断对象是不是参数提供的类型*/ - (BOOL)conformsToProtocol:(Protocol *)aProtocol; /* 用于判断对象是否遵守了参数提供的协议*/ - (BOOL)respondsToSelector:(SEL)aSelector; /* 用于判断对象是否拥有参数提供的方法*/ - (id)retain; //增加对象的计数器 - (oneway void)release; //减少对象的计数器 - (id)autorelease; //自动减少对象的计数器,但是以推迟的方式来实现 - (NSUInteger)retainCount; //返回一个对象当前的计数器 - (NSString *)description; //允许一个对象返回一个字符串来描述它的内容;这个常用于调试debugging @end //表示结束 @protocol NSCopying //NSCopying协议 - (id)copyWithZone:(NSZone *)zone; //协议中的方法是每个采用者必须实现的方法,这里只有一个方法 @end //表示结束 @protocol NSMutableCopying//NSMutableCopying协议 - (id)mutableCopyWithZone:(NSZone *)zone; @end //表示结束 @protocol NSCoding //NSCoding协议 - (void)encodeWithCoder:(NSCoder *)aCoder; - (id)initWithCoder:(NSCoder *)aDecoder; @end /*********** Base class ***********/ @interface NSObject <NSObject> { //告诉编译器,NSObject正在遵守NSObject协议 Class isa; } + (void)load; + (void)initialize; - (id)init; //对象的属性初始化 + (id)new; + (id)allocWithZone:(NSZone *)zone; + (id)alloc; - (void)dealloc; //用于类来释放对象实例变量并释放动态内存 - (void)finalize AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; - (id)copy; - (id)mutableCopy; + (id)copyWithZone:(NSZone *)zone; + (id)mutableCopyWithZone:(NSZone *)zone; + (Class)superclass; + (Class)class; + (BOOL)instancesRespondToSelector:(SEL)aSelector; + (BOOL)conformsToProtocol:(Protocol *)protocol; - (IMP)methodForSelector:(SEL)aSelector; + (IMP)instanceMethodForSelector:(SEL)aSelector; - (void)doesNotRecognizeSelector:(SEL)aSelector; - (id)forwardingTargetForSelector:(SEL)aSelector; - (void)forwardInvocation:(NSInvocation *)anInvocation; - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector; + (NSString *)description; + (BOOL)isSubclassOfClass:(Class)aClass AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER; + (BOOL)resolveClassMethod:(SEL)sel AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; + (BOOL)resolveInstanceMethod:(SEL)sel AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; @end @interface NSObject (NSCoderMethods) //类别 见2.5.3 + (NSInteger)version; + (void)setVersion:(NSInteger)aVersion; - (Class)classForCoder; - (id)replacementObjectForCoder:(NSCoder *)aCoder; - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder; @end #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) @interface NSObject (NSDeprecatedMethods) + (void)poseAsClass:(Class)aClass DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER #if __OBJC2__ UNAVAILABLE_ATTRIBUTE #endif ; @end #endif #if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED