黑马程序员——入学Blog08----分类

来源:互联网 发布:21端口入侵工具 编辑:程序博客网 时间:2024/04/27 18:21
-----------android培训java培训iOS培训、.Net培训、期待与您交流!------------ 
       在介绍分类作用是什么之前,先看一下NSObject类的声明:
@interface NSObject <NSObject> {    Classisa;}+ (void)load;+ (void)initialize;- (id)init;+ (id)new;+ (id)allocWithZone:(NSZone *)zone;+ (id)alloc;- (void)dealloc;- (void)finalize;- (id)copy;- (id)mutableCopy;+ (id)copyWithZone:(NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;+ (id)mutableCopyWithZone:(NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;+ (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 NS_AVAILABLE(10_5, 2_0);- (void)forwardInvocation:(NSInvocation *)anInvocation;- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;- (BOOL)allowsWeakReference NS_UNAVAILABLE;- (BOOL)retainWeakReference NS_UNAVAILABLE;+ (NSString *)description;+ (BOOL)isSubclassOfClass:(Class)aClass;+ (BOOL)resolveClassMethod:(SEL)sel NS_AVAILABLE(10_5, 2_0);+ (BOOL)resolveInstanceMethod:(SEL)sel NS_AVAILABLE(10_5, 2_0);@end@interface NSObject (NSCoderMethods)  // < 1 >+ (NSInteger)version;+ (void)setVersion:(NSInteger)aVersion;- (Class)classForCoder;- (id)replacementObjectForCoder:(NSCoder *)aCoder;- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder NS_REPLACES_RECEIVER;@end

//  main.m#import <Foundation/Foundation.h>#import "NSString+WDL.h"int main(int argc, const char * argv[]){    @autoreleasepool {        NSLog(@"version = %ld",[NSObject version]);    }    return 0;}
运行结果:

       虽然在NSObject中没有version这个类方法,但是因为有< 1 >处的代码,NSObject就能调用version方法了,< 1 >处的写法就是分类。分类是指按照种类、等级或性质分别归类。分类的作用大致有以下3点:
       1.通过分类可以使类的整体结构变得模块化,更加清晰
       2.多人开发同一个类的情况下,使用分类可以避免文件更改的冲突
       3.扩展某个类的功能以满足需求,比如NSString类,可以通过分类扩展逆序输出字符串等方法。
      分类使用上需要注意的地方
        1.分类只能用来增加方法,不能增加成员变量
        2.分类方法的实现中可以访问原来类中声明的成员变量
        3.分类可以重新实现原来类中的方法,但是会覆盖原来的方法,导致原来的方法无法再使用,所以建议不要重新实现
        4.方法调用的优先级: 分类(后编译的优先) > 原来类 > 父类

////  main.m#import <Foundation/Foundation.h>#import "Person.h"#import "Person+Life.h"#import "Person+Job.h"int main(int argc, const char * argv[]){    @autoreleasepool {        Person *p = [[Person alloc] init];        // 原来类与两个分类都有breath,观察会调用哪个        [p breath];                // 生活分类的两个方法        [p eat];        [p sleep];                // 工作分类的两个方法 访问了原来类的成员变量        [p doCoder];        [p searchData];                    }    return 0;}

////  Person.h#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic,assign) int age;// 呼吸- (void) breath;@end

////  Person.m#import "Person.h"@implementation Person// 呼吸- (void) breath{    NSLog(@"一呼一吸");}@end

////  Person+Life.h#import "Person.h"@interface Person (Life)// 吃饭- (void) eat;// 睡觉- (void) sleep;// 呼吸- (void) breath;@end

////  Person+Life.m#import "Person+Life.h"@implementation Person (Life)// 吃饭- (void) eat{    NSLog(@"吃饭");}// 睡觉- (void) sleep{    NSLog(@"睡觉");}// 呼吸- (void) breath{    NSLog(@"生活需要呼吸");}@end

////  Person+Job.h#import "Person.h"@interface Person (Job)// 敲代码- (void) doCoder;// 找资料- (void) searchData;// 呼吸- (void) breath;@end

////  Person+Job.m#import "Person+Job.h"@implementation Person (Job)// 敲代码- (void) doCoder{    NSLog(@"敲代码");    [self setAge:24];  // 设置年龄}// 找资料- (void) searchData{    NSLog(@"找资料");    NSLog(@"这个人多少岁:%d",[self age]);}// 呼吸- (void) breath{    NSLog(@"工作需要呼吸");}@end

运行结果:
  
看文件编译的先后
  
所以breath方法调用的是Life分类中的
最后的打印输出证明了分类方法可以直接访问原来类的成员变量

        下面使用分类来扩展类NSString
//  main.m#import <Foundation/Foundation.h>#import "Person.h"#import "Person+Life.h"#import "Person+Job.h"#import "NSString+Change.h"int main(int argc, const char * argv[]){    @autoreleasepool {        NSString *str = [NSString getReverseString:@"Welcome to beijing"];        NSLog(@"str逆序输出为:%@",str);    }    return 0;}

//  NSString+Change.h#import <Foundation/Foundation.h>@interface NSString (Change)// OC字符串逆序输出+(NSString *)getReverseString:(NSString *)str;@end

////  NSString+Change.m#import "NSString+Change.h"@implementation NSString (Change)// OC字符串逆序输出+(NSString *)getReverseString:(NSString *)str{    NSMutableString *mstr = [NSMutableString stringWithString:str];    for (int i = 0; i < str.length / 2; i++)    {        // 声明两个NSRange变量,保存前后两边的一个字符        NSRange range1 = NSMakeRange(i, 1);        NSRange range2 = NSMakeRange(str.length - i - 1 ,1);        // 从左到右,依次取出字符串中的每个字符        NSString *subStr1 = [str substringWithRange:range1];                // 从右到左,依次取出字符串中的每个字符        NSString *subStr2 = [str substringWithRange:range2];                // 交换前后两个字符        [mstr replaceCharactersInRange:range1 withString:subStr2];        [mstr replaceCharactersInRange:range2 withString:subStr1];    }    return [NSString stringWithFormat:@"%@",mstr];}@end

运行结果:

     分析:因为没有访问成员变量,所以写成了类方法,因为是依次从左与从右取出一个字符,然后进行交换,所以只要做字符串长度的一半的次数就好了

0 0
原创粉丝点击